aspect-build / aspect-build/rules_js
[FR]: Make `_npm_lock_imports_bzlmod` part of the public API
- Dominant language
- Starlark
- Stars
- 378
- Forks
- 183
- Avg merge
- 1d 9h
- Merged PRs (30d)
- 32
Description
### What is the current behavior?
Currently, `_npm_lock_imports_bzlmod` is a private API.
### Describe the feature
Making this function public would make it possible to write 3rd-party rulesets that download an executable package, like Vite, and expose it as a tool by reusing it in custom Bzlmod extensions. This would allow for serving a completely hermetic tool executable that doesn't require having it installed on the build machine. We do this internally, but had to copy this function to the ruleset implementation, which obviously is not ideal.
Currently working example:
```starlark
# MODULE.bazel
my_tool = use_extension("@rules_tool//tool:extensions.bzl", "tool")
my_tool.tool(version = "1.2.3")
# @rules_tool//tool:extensions.bzl
def register_tool(module_ctx, name, version):
"""Set up a private npm_translate_lock repository, and use it to
expose a tool repository.
Args:
module_ctx: The module context.
name: The name of the toolchain repository.
version: The version of the tool to use. Must be present in
TOOL_VERSIONS.
"""
if version not in TOOL_VERSIONS:
fail("Invalid version: {version}. Must be one of: {versions}".format(
version = version,
versions = TOOL_VERSIONS,
))
lockfile_path = "@rules_tool//tool/private/lockfiles/{version}:pnpm-lock.yaml".format(
version = version,
)
pnpm_lock = Label(lockfile_path)
npm_translate_lock(
name = name + "_tool_npm",
pnpm_lock = pnpm_lock,
bzlmod = True,
generate_bzl_library_targets = True,
# NOTE: Extension modules don't run on the BUILD thread so they can't
# call native.register_toolchains. We will register them ourselves
# later.
register_copy_directory_toolchains = False,
register_copy_to_directory_toolchains = False,
register_yq_toolchains = False,
register_tar_toolchains = False,
root_package = "",
)
npm_lock_imports(
module_ctx = module_ctx,
attr = struct(
# Relevant options
name = name + "_tool_npm",
pnpm_lock = pnpm_lock,
generate_bzl_library_targets = True,
root_package = "",
link_workspace = "my_tool",
# pnpm options
prod = True,
dev = False,
no_optional = False,
# Defaults from @aspect_rules_js//npm:extensions.bzl
bins = {},
custom_postinstalls = {},
package_visibility = {},
public_hoist_packages = {},
run_lifecycle_hooks = True,
lifecycle_hooks = {},
lifecycle_hooks_envs = {},
lifecycle_hooks_exclude = [],
lifecycle_hooks_execution_requirements = {},
lifecycle_hooks_no_sandbox = True,
lifecycle_hooks_use_default_shell_env = {},
npmrc = None,
patch_args = {},
patches = {},
replace_packages = {},
update_pnpm_lock = False,
use_home_npmrc = False,
use_starlark_yaml_parser = False,
yq_toolchain_prefix = "yq",
),
)
tool_repository(
name = name + "_tool",
user_repository_name = name,
version = version,
)
```
Here, `npm_lock_imports` is the `_npm_lock_imports_bzlmod` function copied into the ruleset directly. This requires us to import from `@rules_js//npm/private` which is not great.
Contributor guide
Assessment
This issue has not been assessed yet.