Skip to content

Commit ede5b45

Browse files
committed
feat: add prod and dev attributes to npm_link_targets
1 parent 1b32c63 commit ede5b45

File tree

7 files changed

+389
-327
lines changed

7 files changed

+389
-327
lines changed

npm/extensions.bzl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ WARNING: Cannot determine home directory in order to load home `.npmrc` file in
136136
system_tar = detect_system_tar(module_ctx)
137137

138138
for i in imports:
139+
link_packages = {}
140+
for link_package, link_names in i.link_packages.items():
141+
link_packages[link_package] = [link_name["pkg"] for link_name in link_names]
139142
npm_import(
140143
name = i.name,
141144
bins = i.bins,
@@ -149,7 +152,7 @@ WARNING: Cannot determine home directory in order to load home `.npmrc` file in
149152
lifecycle_hooks_env = i.lifecycle_hooks_env,
150153
lifecycle_hooks_execution_requirements = i.lifecycle_hooks_execution_requirements,
151154
lifecycle_hooks_use_default_shell_env = i.lifecycle_hooks_use_default_shell_env,
152-
link_packages = i.link_packages,
155+
link_packages = link_packages,
153156
# attr.pnpm_lock.repo_name is a canonical repository name, so it needs to be qualified with an extra '@'.
154157
link_workspace = attr.link_workspace if attr.link_workspace else "@" + attr.pnpm_lock.repo_name,
155158
npm_auth = i.npm_auth,

npm/private/BUILD.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ exports_files(["noop.sh"])
2929
"npm_translate_lock_generate.docs.bzl",
3030
])
3131
for j, expected in enumerate([
32-
"""def npm_link_targets(name = "node_modules", package = None):""",
33-
"""def npm_link_all_packages(name = "node_modules", imported_links = []):""",
32+
"""def npm_link_targets(name = "node_modules", package = None, prod = False, dev = False):""",
33+
"""def npm_link_all_packages(name = "node_modules", imported_links = [], prod = False, dev = False):""",
3434
])
3535
]
3636

npm/private/npm_translate_lock_generate.bzl

Lines changed: 89 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ _FP_DIRECT_TMPL = \
6565

6666
_FP_DIRECT_TARGET_TMPL = \
6767
"""
68-
if bazel_package in {link_packages}:
68+
if bazel_package in {link_packages} and ((not prod and not dev) or {prod_or_dev}):
6969
link_targets.append(":{{}}/{pkg}".format(name))"""
7070

7171
_BZL_LIBRARY_TMPL = \
@@ -151,62 +151,66 @@ sh_binary(
151151
"package": name,
152152
"path": dep_path,
153153
"link_packages": {},
154+
"link_dev_packages": {},
154155
"deps": transitive_deps,
155156
}
156157

157158
# Look for first-party links in importers
158159
for import_path, importer in importers.items():
159-
dependencies = importer.get("all_deps")
160-
if type(dependencies) != "dict":
161-
msg = "expected dict of dependencies in processed importer '{}'".format(import_path)
162-
fail(msg)
163160
link_package = helpers.link_package(root_package, import_path)
164-
for dep_package, dep_version in dependencies.items():
165-
if dep_version.startswith("file:"):
166-
dep_key = "{}+{}".format(dep_package, dep_version)
167-
if not dep_key in fp_links.keys():
168-
msg = "Expected to file: referenced package {} in first-party links {}".format(dep_key, fp_links.keys())
169-
fail(msg)
170-
fp_links[dep_key]["link_packages"][link_package] = True
171-
elif dep_version.startswith("link:"):
172-
dep_link = dep_version[len("link:"):]
173-
dep_path = helpers.link_package(root_package, dep_link)
174-
dep_key = "{}+{}".format(dep_package, dep_path)
175-
if fp_links.get(dep_key, False):
176-
fp_links[dep_key]["link_packages"][link_package] = True
177-
else:
178-
transitive_deps = {}
179-
raw_deps = {}
180-
if importers.get(dep_link, False):
181-
raw_deps = importers.get(dep_link).get("deps")
182-
for raw_package, raw_version in raw_deps.items():
183-
package_store_name = utils.package_store_name(raw_package, raw_version)
184-
dep_store_target = """"//{root_package}:{package_store_root}/{{}}/{package_store_name}".format(name)""".format(
185-
root_package = root_package,
186-
package_store_name = package_store_name,
187-
package_store_root = utils.package_store_root,
188-
)
189-
if dep_store_target not in transitive_deps:
190-
transitive_deps[dep_store_target] = [raw_package]
191-
else:
192-
transitive_deps[dep_store_target].append(raw_package)
193-
194-
# collapse link aliases lists into to a comma separated strings
195-
for dep_store_target in transitive_deps.keys():
196-
transitive_deps[dep_store_target] = ",".join(transitive_deps[dep_store_target])
197-
fp_links[dep_key] = {
198-
"package": dep_package,
199-
"path": dep_path,
200-
"link_packages": {link_package: True},
201-
"deps": transitive_deps,
202-
}
161+
for deps_type, link_type in [("deps", "link_packages"), ("dev_deps", "link_dev_packages")]:
162+
dependencies = importer.get(deps_type)
163+
if type(dependencies) != "dict":
164+
msg = "expected dict of dependencies in processed importer '{}'".format(import_path)
165+
fail(msg)
166+
for dep_package, dep_version in dependencies.items():
167+
if dep_version.startswith("file:"):
168+
dep_key = "{}+{}".format(dep_package, dep_version)
169+
if not dep_key in fp_links.keys():
170+
msg = "Expected to file: referenced package {} in first-party links {}".format(dep_key, fp_links.keys())
171+
fail(msg)
172+
fp_links[dep_key][link_type][link_package] = True
173+
elif dep_version.startswith("link:"):
174+
dep_link = dep_version[len("link:"):]
175+
dep_path = helpers.link_package(root_package, dep_link)
176+
dep_key = "{}+{}".format(dep_package, dep_path)
177+
if not fp_links.get(dep_key, False):
178+
transitive_deps = {}
179+
raw_deps = {}
180+
if importers.get(dep_link, False):
181+
raw_deps = importers.get(dep_link).get("deps")
182+
for raw_package, raw_version in raw_deps.items():
183+
package_store_name = utils.package_store_name(raw_package, raw_version)
184+
dep_store_target = """"//{root_package}:{package_store_root}/{{}}/{package_store_name}".format(name)""".format(
185+
root_package = root_package,
186+
package_store_name = package_store_name,
187+
package_store_root = utils.package_store_root,
188+
)
189+
if dep_store_target not in transitive_deps:
190+
transitive_deps[dep_store_target] = [raw_package]
191+
else:
192+
transitive_deps[dep_store_target].append(raw_package)
193+
194+
# collapse link aliases lists into to a comma separated strings
195+
for dep_store_target in transitive_deps.keys():
196+
transitive_deps[dep_store_target] = ",".join(transitive_deps[dep_store_target])
197+
fp_links[dep_key] = {
198+
"package": dep_package,
199+
"path": dep_path,
200+
"link_packages": {},
201+
"link_dev_packages": {},
202+
"deps": transitive_deps,
203+
}
204+
fp_links[dep_key][link_type][link_package] = True
203205

204206
npm_link_packages_const = """_LINK_PACKAGES = {link_packages}""".format(link_packages = str(link_packages))
205207

206208
npm_link_targets_bzl = [
207209
"""\
208210
# buildifier: disable=function-docstring
209-
def npm_link_targets(name = "node_modules", package = None):
211+
def npm_link_targets(name = "node_modules", package = None, prod = False, dev = False):
212+
if prod and dev:
213+
fail("prod and dev attributes cannot both be set to true")
210214
bazel_package = package if package != None else native.package_name()
211215
link = bazel_package in _LINK_PACKAGES
212216
@@ -217,7 +221,7 @@ def npm_link_targets(name = "node_modules", package = None):
217221
npm_link_all_packages_bzl = [
218222
"""\
219223
# buildifier: disable=function-docstring
220-
def npm_link_all_packages(name = "node_modules", imported_links = []):
224+
def npm_link_all_packages(name = "node_modules", imported_links = [], prod = False, dev = False):
221225
bazel_package = native.package_name()
222226
root_package = "{root_package}"
223227
is_root = bazel_package == root_package
@@ -266,9 +270,7 @@ def npm_link_all_packages(name = "node_modules", imported_links = []):
266270
)
267271

268272
stores_bzl.append(""" store_{i}(name)""".format(i = i))
269-
for link_package, _link_aliases in _import.link_packages.items():
270-
link_aliases = _link_aliases or [_import.package]
271-
273+
for link_package, link_names in _import.link_packages.items():
272274
# the build file for the package being linked
273275
build_file = "{}/{}".format(link_package, "BUILD.bazel") if link_package else "BUILD.bazel"
274276
if build_file not in rctx_files:
@@ -281,7 +283,10 @@ def npm_link_all_packages(name = "node_modules", imported_links = []):
281283
links_targets_bzl[link_package] = []
282284

283285
# for each alias of this package
284-
for link_alias in link_aliases:
286+
for link_name in link_names:
287+
link_alias = link_name["pkg"]
288+
dev = link_name["dev"]
289+
285290
# link the alias to the underlying package
286291
links_bzl[link_package].append(""" link_{i}("{{}}/{alias}".format(name), link_root_name = name, link_alias = "{alias}")""".format(
287292
i = i,
@@ -290,7 +295,7 @@ def npm_link_all_packages(name = "node_modules", imported_links = []):
290295

291296
# expose the alias if public
292297
if "//visibility:public" in _import.package_visibility:
293-
add_to_link_targets = """ link_targets.append(":{{}}/{alias}".format(name))""".format(alias = link_alias)
298+
add_to_link_targets = """ link_targets.append(":{{}}/{alias}".format(name)) if (not prod and not dev) or {prod_or_dev} else None""".format(alias = link_alias, prod_or_dev = "dev" if dev else "prod")
294299
links_bzl[link_package].append(add_to_link_targets)
295300
links_targets_bzl[link_package].append(add_to_link_targets)
296301
package_scope = link_alias[:link_alias.find("/", 1)] if link_alias[0] == "@" else None
@@ -314,19 +319,19 @@ def npm_link_all_packages(name = "node_modules", imported_links = []):
314319
if rctx.attr.generate_bzl_library_targets:
315320
rctx_files[build_file].append("""load("@bazel_skylib//:bzl_library.bzl", "bzl_library")""")
316321

317-
for link_alias in link_aliases:
322+
for link_name in link_names:
318323
rctx_files[build_file].append(_BZL_LIBRARY_TMPL.format(
319-
name = link_alias,
320-
src = ":{}/{}".format(link_alias, _PACKAGE_JSON_BZL_FILENAME),
324+
name = link_name["pkg"],
325+
src = ":{}/{}".format(link_name["pkg"], _PACKAGE_JSON_BZL_FILENAME),
321326
dep = "@{repo_name}//{link_package}:{package_name}_bzl_library".format(
322327
repo_name = helpers.to_apparent_repo_name(_import.name),
323328
link_package = link_package,
324-
package_name = link_package[link_package.rfind("/") + 1] if link_package else link_alias.split("/")[-1],
329+
package_name = link_package[link_package.rfind("/") + 1] if link_package else link_name["pkg"].split("/")[-1],
325330
),
326331
))
327332

328-
for link_alias in link_aliases:
329-
package_json_bzl_file_path = "{}/{}/{}".format(link_package, link_alias, _PACKAGE_JSON_BZL_FILENAME) if link_package else "{}/{}".format(link_alias, _PACKAGE_JSON_BZL_FILENAME)
333+
for link_name in link_names:
334+
package_json_bzl_file_path = "{}/{}/{}".format(link_package, link_name["pkg"], _PACKAGE_JSON_BZL_FILENAME) if link_package else "{}/{}".format(link_name["pkg"], _PACKAGE_JSON_BZL_FILENAME)
330335
repo_package_json_bzl = "@@{repo_name}//{link_package}:{package_json_bzl}".format(
331336
repo_name = _import.name,
332337
link_package = link_package,
@@ -368,7 +373,6 @@ def npm_link_all_packages(name = "node_modules", imported_links = []):
368373
for fp_link in fp_links.values():
369374
fp_package = fp_link.get("package")
370375
fp_path = fp_link.get("path")
371-
fp_link_packages = fp_link.get("link_packages").keys()
372376
fp_deps = fp_link.get("deps")
373377
fp_target = "//{}:{}".format(
374378
fp_path,
@@ -387,28 +391,31 @@ def npm_link_all_packages(name = "node_modules", imported_links = []):
387391
if len(package_visibility) == 0:
388392
package_visibility = ["//visibility:public"]
389393

390-
if len(fp_link_packages) > 0:
391-
npm_link_all_packages_bzl.append(_FP_DIRECT_TMPL.format(
392-
link_packages = fp_link_packages,
393-
link_visibility = package_visibility,
394-
pkg = fp_package,
395-
package_directory_output_group = utils.package_directory_output_group,
396-
root_package = root_package,
397-
package_store_name = utils.package_store_name(fp_package, "0.0.0"),
398-
package_store_root = utils.package_store_root,
399-
))
394+
for link_type in ["link_packages", "link_dev_packages"]:
395+
fp_link_packages = fp_link.get(link_type).keys()
396+
if len(fp_link_packages) > 0:
397+
npm_link_all_packages_bzl.append(_FP_DIRECT_TMPL.format(
398+
link_packages = fp_link_packages,
399+
link_visibility = package_visibility,
400+
pkg = fp_package,
401+
package_directory_output_group = utils.package_directory_output_group,
402+
root_package = root_package,
403+
package_store_name = utils.package_store_name(fp_package, "0.0.0"),
404+
package_store_root = utils.package_store_root,
405+
))
400406

401-
npm_link_targets_bzl.append(_FP_DIRECT_TARGET_TMPL.format(
402-
link_packages = fp_link_packages,
403-
pkg = fp_package,
404-
))
407+
npm_link_targets_bzl.append(_FP_DIRECT_TARGET_TMPL.format(
408+
link_packages = fp_link_packages,
409+
pkg = fp_package,
410+
prod_or_dev = "dev" if link_type == "link_dev_packages" else "prod",
411+
))
405412

406-
if "//visibility:public" in package_visibility:
407-
add_to_link_targets = """ link_targets.append(":{{}}/{pkg}".format(name))""".format(pkg = fp_package)
408-
npm_link_all_packages_bzl.append(add_to_link_targets)
409-
package_scope = fp_package[:fp_package.find("/", 1)] if fp_package[0] == "@" else None
410-
if package_scope:
411-
npm_link_all_packages_bzl.append(_ADD_SCOPE_TARGET2.format(package_scope = package_scope))
413+
if "//visibility:public" in package_visibility:
414+
add_to_link_targets = """ link_targets.append(":{{}}/{pkg}".format(name))""".format(pkg = fp_package)
415+
npm_link_all_packages_bzl.append(add_to_link_targets)
416+
package_scope = fp_package[:fp_package.find("/", 1)] if fp_package[0] == "@" else None
417+
if package_scope:
418+
npm_link_all_packages_bzl.append(_ADD_SCOPE_TARGET2.format(package_scope = package_scope))
412419

413420
# Generate catch all & scoped js_library targets
414421
npm_link_all_packages_bzl.append("""
@@ -543,8 +550,11 @@ def _gen_npm_import(rctx, system_tar, _import, link_workspace):
543550
maybe_exclude_package_contents = ("""
544551
exclude_package_contents = %s,""" % _import.exclude_package_contents) if _import.exclude_package_contents != None else ""
545552

553+
link_packages = {}
554+
for link_package, link_names in _import.link_packages.items():
555+
link_packages[link_package] = [link_name["pkg"] for link_name in link_names]
546556
return _NPM_IMPORT_TMPL.format(
547-
link_packages = starlark_codegen_utils.to_dict_attr(_import.link_packages, 2, quote_value = False),
557+
link_packages = starlark_codegen_utils.to_dict_attr(link_packages, 2, quote_value = False),
548558
link_workspace = link_workspace,
549559
maybe_bins = maybe_bins,
550560
maybe_commit = maybe_commit,

npm/private/npm_translate_lock_generate.docs.bzl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ load("@npm//:defs.bzl", "npm_link_targets", "npm_link_all_packages")
1717
# Instead, we define the interfaces in this file, while the implementations live in npm_translate_lock_generate.bzl.
1818

1919
# buildifier: disable=unused-variable
20-
def npm_link_targets(name = "node_modules", package = None):
20+
def npm_link_targets(name = "node_modules", package = None, prod = False, dev = False):
2121
"""Generated list of target names that are linked by npm_link_all_packages()
2222
2323
Args:
@@ -27,14 +27,16 @@ def npm_link_targets(name = "node_modules", package = None):
2727
Set to an empty string "" to specify the root package.
2828
2929
If unspecified, the current package (`native.package_name()`) is used.
30+
prod: when True, only include production dependencies
31+
dev: when True, only include development dependencies
3032
3133
Returns:
3234
A list of target names that are linked by npm_link_all_packages()
3335
"""
3436
pass
3537

3638
# buildifier: disable=unused-variable
37-
def npm_link_all_packages(name = "node_modules", imported_links = []):
39+
def npm_link_all_packages(name = "node_modules", imported_links = [], prod = False, dev = False):
3840
"""Generated list of npm_link_package() target generators and first-party linked packages corresponding to the packages in {pnpm_lock_label}
3941
4042
If you use manually-written [`npm_import`](/docs/npm_import.md#npm_import) you can link these as well, for example,
@@ -52,5 +54,7 @@ def npm_link_all_packages(name = "node_modules", imported_links = []):
5254
Args:
5355
name: name of catch all target to generate for all packages linked
5456
imported_links: optional list link functions from manually imported packages that were fetched with npm_import rules.
57+
prod: when True, only include production dependencies
58+
dev: when True, only include development dependencies
5559
"""
5660
pass

0 commit comments

Comments
 (0)