@@ -34,12 +34,37 @@ load(
3434 "copy_cmd" ,
3535)
3636
37- _AMD_NAMES_DOC = """Mapping from require module names to global variables.
38- This allows devmode JS sources to load unnamed UMD bundles from third-party libraries."""
37+ _ATTRS = {
38+ "amd_names" : attr .string_dict (
39+ doc = """Non-public legacy API, not recommended to make new usages.
40+ See documentation on AmdNamesInfo""" ,
41+ ),
42+ "deps" : attr .label_list (),
43+ "is_windows" : attr .bool (
44+ doc = "Internal use only. Automatically set by macro" ,
45+ mandatory = True ,
46+ ),
47+ # module_name for legacy ts_library module_mapping support
48+ # which is still being used in a couple of tests
49+ # TODO: remove once legacy module_mapping is removed
50+ "module_name" : attr .string (
51+ doc = "Internal use only. It will be removed soon." ,
52+ ),
53+ "named_module_srcs" : attr .label_list (
54+ doc = """Non-public legacy API, not recommended to make new usages.
55+ A subset of srcs that are javascript named-UMD or
56+ named-AMD for use in rules such as ts_devserver.
57+ They will be copied into the package bin folder if needed.""" ,
58+ allow_files = True ,
59+ ),
60+ "package_name" : attr .string (),
61+ "srcs" : attr .label_list (allow_files = True ),
62+ }
3963
4064AmdNamesInfo = provider (
41- doc = "provide access to the amd_names attribute of js_library" ,
42- fields = {"names" : _AMD_NAMES_DOC },
65+ doc = "Non-public API. Provides access to the amd_names attribute of js_library" ,
66+ fields = {"names" : """Mapping from require module names to global variables.
67+ This allows devmode JS sources to load unnamed UMD bundles from third-party libraries.""" },
4368)
4469
4570def write_amd_names_shim (actions , amd_names_shim , targets ):
@@ -48,7 +73,7 @@ def write_amd_names_shim(actions, amd_names_shim, targets):
4873 These are collected from our bootstrap deps (the only place global scripts should appear)
4974
5075 Args:
51- actions: skylark rule execution context.actions
76+ actions: starlark rule execution context.actions
5277 amd_names_shim: File where the shim is written
5378 targets: dependencies to be scanned for AmdNamesInfo providers
5479 """
@@ -199,57 +224,88 @@ def _impl(ctx):
199224
200225_js_library = rule (
201226 implementation = _impl ,
202- attrs = {
203- "amd_names" : attr .string_dict (
204- doc = _AMD_NAMES_DOC ,
205- ),
206- "deps" : attr .label_list (
207- doc = """Transitive dependencies of the package.
208- It should include fine grained npm dependencies from the sources
209- or other targets we want to include in the library but also propagate their own deps.""" ,
210- ),
211- "is_windows" : attr .bool (
212- doc = "Automatically set by macro" ,
213- mandatory = True ,
214- ),
215- # module_name for legacy ts_library module_mapping support
216- # which is still being used in a couple of tests
217- # TODO: remove once legacy module_mapping is removed
218- "module_name" : attr .string (
219- doc = "Internal use only. It will be removed soon." ,
220- ),
221- "named_module_srcs" : attr .label_list (
222- doc = """A subset of srcs that are javascript named-UMD or
223- named-AMD for use in rules such as ts_devserver.
224- They will be copied into the package bin folder if needed.""" ,
225- allow_files = True ,
226- ),
227- "package_name" : attr .string (
228- doc = """Optional package_name that this package may be imported as.""" ,
229- ),
230- "srcs" : attr .label_list (
231- doc = """The list of files that comprise the package.
232- They will be copied into the package bin folder if needed.""" ,
233- allow_files = True ,
234- ),
235- },
236- doc = "Defines a js_library package" ,
227+ attrs = _ATTRS ,
237228)
238229
239230def js_library (
240231 name ,
241232 srcs = [],
242- amd_names = {},
243233 package_name = None ,
244234 deps = [],
245- named_module_srcs = [],
246235 ** kwargs ):
247- """Internal use only yet. It will be released into a public API in a future release."""
236+ """Groups JavaScript code so that it can be depended on like an npm package.
237+
238+ ### Behavior
239+
240+ This rule doesn't perform any build steps ("actions") so it is similar to a `filegroup`.
241+ However it produces several Bazel "Providers" for interop with other rules.
242+
243+ > Compare this to `pkg_npm` which just produces a directory output, and therefore can't expose individual
244+ > files to downstream targets and causes a cascading re-build of all transitive dependencies when any file
245+ > changes
246+
247+ These providers are:
248+ - DeclarationInfo so this target can be a dependency of a TypeScript rule
249+ - NpmPackageInfo so this target can interop with rules that expect third-party npm packages
250+ - LinkablePackageInfo for use with our "linker" that makes this package importable (similar to `npm link`)
251+ - JsModuleInfo so rules like bundlers can collect the transitive set of .js files
252+
253+ `js_library` also copies any source files into the bazel-out folder.
254+ This is the same behavior as the `copy_to_bin` rule.
255+ By copying the complete package to the output tree, we ensure that the linker (our `npm link` equivalent)
256+ will make your source files available in the node_modules tree where resolvers expect them.
257+ It also means you can have relative imports between the files
258+ rather than being forced to use Bazel's "Runfiles" semantics where any program might need a helper library
259+ to resolve files between the logical union of the source tree and the output tree.
260+
261+ ### Usage
262+
263+ `js_library` is intended to be used internally within Bazel, such as between two libraries in your monorepo.
264+
265+ > Compare this to `pkg_npm` which is intended to publish your code for external usage outside of Bazel, like
266+ > by publishing to npm or artifactory.
267+
268+ The typical example usage of `js_library` is to expose some sources with a package name:
269+
270+ ```python
271+ ts_project(
272+ name = "compile_ts",
273+ srcs = glob(["*.ts"]),
274+ )
275+
276+ js_library(
277+ name = "my_pkg",
278+ # Code that depends on this target can import from "@myco/mypkg"
279+ package_name = "@myco/mypkg",
280+ # Consumers might need fields like "main" or "typings"
281+ srcs = ["package.json"],
282+ # The .js and .d.ts outputs from above will be part of the package
283+ deps = [":compile_ts"],
284+ )
285+ ```
286+
287+ To help work with "named AMD" modules as required by `ts_devserver` and other Google-style "concatjs" rules,
288+ `js_library` has some undocumented advanced features you can find in the source code or in our examples.
289+ These should not be considered a public API and aren't subject to our usual support and semver guarantees.
290+
291+ Args:
292+ name: a name for the target
293+ srcs: the list of files that comprise the package
294+ package_name: the name it will be imported by. Should match the "name" field in the package.json file.
295+ deps: other targets that provide JavaScript code
296+ **kwargs: used for undocumented legacy features
297+ """
298+
299+ # Undocumented features
300+ amd_names = kwargs .pop ("amd_names" , {})
248301 module_name = kwargs .pop ("module_name" , None )
302+ named_module_srcs = kwargs .pop ("named_module_srcs" , [])
303+
249304 if module_name :
250305 fail ("use package_name instead of module_name in target //%s:%s" % (native .package_name (), name ))
251306 if kwargs .pop ("is_windows" , None ):
252- fail ("is_windows is set by the js_library macro and should not be set explicitely" )
307+ fail ("is_windows is set by the js_library macro and should not be set explicitly" )
308+
253309 _js_library (
254310 name = name ,
255311 amd_names = amd_names ,
0 commit comments