Skip to content

Commit ad33e61

Browse files
devversionjosephperrott
authored andcommitted
feat(dev-infra): add bazel rule for extracting JavaScript module flavors from targets (#42809)
Introduces a rule that collects declared JavaScript module output files from a list of dependencies based on a configurable JavaScript module provider. The extracted outputs are exposed within the `DefaultInfo` provider. Targets defined using this rule can be used as input for rules that require JavaScript sources, or if there are multiple JavaScript output variants defined for a target while for example only the `JSModuleInfo` outputs are of interest. As an example: This rule is helpful in combination with `ts_library` and `ng_module` as those rule expose multiple output flavors (which are distinguishable by the JavaScript module providers as imported from `providers.bzl`). i.e. these rules expose flavors for named AMD modules and ECMAScript module output. If we want to ship a NPM package only using ECMAScript modules for example, we could extract all `JSEcmaScriptModuleInfo`-denoted output and feed that into the `pkg_npm` rule, compared to bringing in all output flavors. For reference: https://github.com/bazelbuild/rules_nodejs/blob/stable/packages/typescript/internal/build_defs.bzl#L334-L337 PR Close #42809
1 parent 22120db commit ad33e61

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

bazel/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ filegroup(
55
srcs = [
66
"BUILD.bazel",
77
"expand_template.bzl",
8+
"extract_js_module_output.bzl",
89
"//dev-infra/bazel/api-golden:files",
910
"//dev-infra/bazel/browsers:files",
1011
"//dev-infra/bazel/remote-execution:files",

bazel/extract_js_module_output.bzl

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
load("@build_bazel_rules_nodejs//:providers.bzl", "DeclarationInfo", "JSEcmaScriptModuleInfo", "JSModuleInfo", "JSNamedModuleInfo")
2+
3+
"""Converts a provider name to its actually Starlark provider instance."""
4+
5+
def _name_to_js_module_provider(name):
6+
if name == "JSModuleInfo":
7+
return JSModuleInfo
8+
elif name == "JSNamedModuleInfo":
9+
return JSNamedModuleInfo
10+
elif name == "JSEcmaScriptModuleInfo":
11+
return JSEcmaScriptModuleInfo
12+
fail("Unexpected JavaScript module provider.")
13+
14+
"""Implementation of the extract_js_module_output rule."""
15+
16+
def _extract_js_module_output_impl(ctx):
17+
js_module_provider = _name_to_js_module_provider(ctx.attr.provider)
18+
depsets = []
19+
for dep in ctx.attr.deps:
20+
# Include JavaScript sources (including transitive outputs) based on the
21+
# configured JavaScript module provider.
22+
if js_module_provider in dep:
23+
depsets.append(dep[js_module_provider].sources)
24+
25+
# Based on whether declarations should be collected, extract direct
26+
# and transitive declaration files using the `DeclarationInfo` provider.
27+
if ctx.attr.include_declarations and DeclarationInfo in dep:
28+
depsets.append(dep[DeclarationInfo].transitive_declarations)
29+
30+
# Based on whether default files should be collected, extract direct
31+
# files which are exposed using the `DefaultInfo` provider. Also include
32+
# data runfiles which are needed for the current target.
33+
# https://docs.bazel.build/versions/main/skylark/lib/DefaultInfo.html#data_runfiles
34+
if ctx.attr.include_default_files and DefaultInfo in dep:
35+
depsets.append(dep[DefaultInfo].files)
36+
depsets.append(dep[DefaultInfo].data_runfiles.files)
37+
38+
sources = depset(transitive = depsets)
39+
40+
return [DefaultInfo(files = sources)]
41+
42+
"""
43+
Rule that collects declared JavaScript module output files from a list of dependencies
44+
based on a configurable JavaScript module provider. The extracted outputs are exposed
45+
within the `DefaultInfo` provider. Targets defined using this rule can be used as input
46+
for rules that require JavaScript sources, or if there are multiple JavaScript output
47+
variants defined for a target while for example only the `JSModule` outputs are of interest.
48+
49+
As an example: This rule is helpful in combination with `ts_library` and `ng_module` as
50+
those rule expose multiple output flavors (which are distinguishable by the JavaScript module
51+
providers as imported from `providers.bzl`). i.e. these rules expose flavors for named AMD
52+
modules and ECMAScript module output. For reference:
53+
https://github.com/bazelbuild/rules_nodejs/blob/stable/packages/typescript/internal/build_defs.bzl#L334-L337
54+
"""
55+
extract_js_module_output = rule(
56+
implementation = _extract_js_module_output_impl,
57+
attrs = {
58+
"deps": attr.label_list(
59+
allow_files = True,
60+
),
61+
"provider": attr.string(
62+
doc = "JavaScript module info provider that is used for collecting sources from the dependencies.",
63+
mandatory = True,
64+
values = ["JSModuleInfo", "JSNamedModuleInfo", "JSEcmaScriptModuleInfo"],
65+
),
66+
"include_declarations": attr.bool(
67+
mandatory = True,
68+
doc = "Whether declaration files should be collected from the dependencies.",
69+
),
70+
"include_default_files": attr.bool(
71+
mandatory = True,
72+
doc = """
73+
Whether files from the `DefaultInfo` provider should be collected. Includes
74+
data runfiles needed for the default outputs from dependencies.
75+
""",
76+
),
77+
},
78+
)

0 commit comments

Comments
 (0)