fix: do not put sources+types into NpmPackageStoreInfo.files (#1850)
Co-authored-by: Greg Magolan <greg@aspect.dev>
diff --git a/examples/linked_consumer/BUILD.bazel b/examples/linked_consumer/BUILD.bazel
index 5d0c395..662d757 100644
--- a/examples/linked_consumer/BUILD.bazel
+++ b/examples/linked_consumer/BUILD.bazel
@@ -1,4 +1,6 @@
-load("@aspect_rules_js//js:defs.bzl", "js_test")
+load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")
+load("@aspect_bazel_lib//lib:diff_test.bzl", "diff_test")
+load("@aspect_rules_js//js:defs.bzl", "js_info_files", "js_test")
load("@npm//:defs.bzl", "npm_link_all_packages")
npm_link_all_packages(name = "node_modules")
@@ -22,3 +24,77 @@
],
entry_point = "test_pkg_deps_linked.js",
)
+
+# Test that sources & test can be pulled from a linked js_library the same
+# as they can be pulled out of an unlinked js_library
+js_info_files(
+ name = "unlinked_sources",
+ srcs = ["//examples/linked_lib:lib"],
+ include_npm_sources = False,
+ include_sources = True,
+ include_transitive_sources = True,
+ include_transitive_types = False,
+ include_types = False,
+)
+
+js_info_files(
+ name = "linked_sources",
+ srcs = [":node_modules/@lib/test2"],
+ include_npm_sources = False,
+ include_sources = True,
+ include_transitive_sources = True,
+ include_transitive_types = False,
+ include_types = False,
+)
+
+copy_to_directory(
+ name = "unlinked_sources_dir",
+ srcs = [":unlinked_sources"],
+)
+
+copy_to_directory(
+ name = "linked_sources_dir",
+ srcs = [":linked_sources"],
+)
+
+diff_test(
+ name = "sources_test",
+ file1 = ":unlinked_sources_dir",
+ file2 = ":linked_sources_dir",
+)
+
+js_info_files(
+ name = "linked_types",
+ srcs = [":node_modules/@lib/test2"],
+ include_npm_sources = False,
+ include_sources = False,
+ include_transitive_sources = False,
+ include_transitive_types = True,
+ include_types = True,
+)
+
+js_info_files(
+ name = "unlinked_types",
+ srcs = ["//examples/linked_lib:lib"],
+ include_npm_sources = False,
+ include_sources = False,
+ include_transitive_sources = False,
+ include_transitive_types = True,
+ include_types = True,
+)
+
+copy_to_directory(
+ name = "unlinked_types_dir",
+ srcs = [":unlinked_types"],
+)
+
+copy_to_directory(
+ name = "linked_types_dir",
+ srcs = [":linked_types"],
+)
+
+diff_test(
+ name = "types_test",
+ file1 = ":unlinked_types_dir",
+ file2 = ":linked_types_dir",
+)
diff --git a/examples/linked_lib/BUILD.bazel b/examples/linked_lib/BUILD.bazel
index 70b9dd1..82045c6 100644
--- a/examples/linked_lib/BUILD.bazel
+++ b/examples/linked_lib/BUILD.bazel
@@ -9,6 +9,8 @@
name = "pkg",
srcs = [
"index.js",
+ "one.d.ts",
+ "one.js",
"package.json",
],
visibility = ["//visibility:public"],
diff --git a/examples/linked_lib/one.d.ts b/examples/linked_lib/one.d.ts
new file mode 100644
index 0000000..b9dc8dd
--- /dev/null
+++ b/examples/linked_lib/one.d.ts
@@ -0,0 +1 @@
+export declare const one = 1
diff --git a/examples/linked_lib/one.js b/examples/linked_lib/one.js
new file mode 100644
index 0000000..e4d42ee
--- /dev/null
+++ b/examples/linked_lib/one.js
@@ -0,0 +1,4 @@
+'use strict'
+exports.__esModule = true
+exports.one = void 0
+exports.one = 1
diff --git a/npm/private/npm_link_package_store.bzl b/npm/private/npm_link_package_store.bzl
index a1798a4..71c9801 100644
--- a/npm/private/npm_link_package_store.bzl
+++ b/npm/private/npm_link_package_store.bzl
@@ -22,7 +22,7 @@
_ATTRS = {
"src": attr.label(
doc = """The npm_package_store target to link as a direct dependency.""",
- providers = [NpmPackageStoreInfo],
+ providers = [NpmPackageStoreInfo, JsInfo],
mandatory = True,
),
"package": attr.string(
@@ -61,6 +61,7 @@
def _npm_link_package_store_impl(ctx):
store_info = ctx.attr.src[NpmPackageStoreInfo]
+ store_js_info = ctx.attr.src[JsInfo]
package_store_directory = store_info.package_store_directory
if not package_store_directory:
@@ -91,11 +92,28 @@
)
files.append(bin_file)
- files_depset = depset(files, transitive = [store_info.files])
+ # All files required to run the package if consumed as `DefaultInfo`
+ files_depset = depset(files, transitive = [
+ store_info.files,
+ store_js_info.npm_sources,
+ store_js_info.sources,
+ ])
+ transitive_files_depset = depset(files, transitive = [
+ store_info.transitive_files,
+ store_js_info.npm_sources,
+ store_js_info.transitive_sources,
+ ])
- transitive_files_depset = depset(files, transitive = [store_info.transitive_files])
+ # Additional npm_sources required to to run the package, in addition to other
+ # data included in JsInfo provider.
+ npm_sources = depset(files, transitive = [
+ store_info.transitive_files,
+ store_js_info.npm_sources,
+ ])
providers = [
+ # Provide default info to allow consuming the package via `data` of rules
+ # not aware of JsInfo such as `sh_binary` etc.
DefaultInfo(
# Only provide direct files in DefaultInfo files
files = files_depset,
@@ -105,7 +123,11 @@
),
js_info(
target = ctx.label,
- npm_sources = transitive_files_depset,
+ sources = store_js_info.sources,
+ transitive_sources = store_js_info.transitive_sources,
+ types = store_js_info.types,
+ transitive_types = store_js_info.transitive_types,
+ npm_sources = npm_sources,
# only propagate non-dev npm dependencies to use as direct dependencies when linking downstream npm_package targets with npm_link_package
npm_package_store_infos = depset([store_info]) if not store_info.dev else depset(),
),
diff --git a/npm/private/npm_package_store.bzl b/npm/private/npm_package_store.bzl
index 862c0f7..8b3e2a5 100644
--- a/npm/private/npm_package_store.bzl
+++ b/npm/private/npm_package_store.bzl
@@ -105,7 +105,7 @@
> In contrast, Bazel makes it possible to make builds hermetic, which means that
> all dependencies of a program must be declared when running in Bazel's sandbox.
""",
- providers = [NpmPackageStoreInfo],
+ providers = [NpmPackageStoreInfo, JsInfo],
),
"package": attr.string(
doc = """The package name to link to.
@@ -180,9 +180,17 @@
package_store_name = utils.package_store_name(package, version)
package_store_directory = None
+ # files required to create the package store entry
files = []
transitive_files_depsets = []
+
+ # JsInfo of the package and all deps required to run
+ js_infos = []
+
+ # NpmPackageStoreInfo of the package and deps
npm_package_store_infos = []
+
+ # Direct references to all dependencies
direct_ref_deps = {}
# the path to the package store location for this package
@@ -277,6 +285,8 @@
# "node_modules/{package_store_root}/{package_store_name}/node_modules/{package}"
dep_symlink_path = "node_modules/{}/{}/node_modules/{}".format(utils.package_store_root, package_store_name, dep_info.package)
files.append(utils.make_symlink(ctx, dep_symlink_path, dep_package_store_directory.path))
+
+ # Include the store info of all linked dependencies
npm_package_store_infos.append(dep_info)
elif ctx.attr.src and JsInfo in ctx.attr.src:
jsinfo = ctx.attr.src[JsInfo]
@@ -287,10 +297,8 @@
else:
symlink_path = "{}/{}".format(ctx.label.package or ".", package_store_directory_path)
- transitive_files_depsets.append(jsinfo.npm_sources)
- transitive_files_depsets.append(jsinfo.transitive_sources)
- transitive_files_depsets.append(jsinfo.transitive_types)
- npm_package_store_infos.extend(jsinfo.npm_package_store_infos.to_list())
+ # The package JsInfo including all direct and transitive sources, store info etc.
+ js_infos.append(jsinfo)
if jsinfo.target.workspace_name:
target_path = "{}/external/{}/{}".format(ctx.bin_dir.path, jsinfo.target.workspace_name, jsinfo.target.package)
@@ -346,10 +354,14 @@
if package_store_directory:
files.append(package_store_directory)
+ # Include the store and js info of all dependencies expected to be linked
for target in ctx.attr.deps:
+ js_infos.append(target[JsInfo])
npm_package_store_infos.append(target[NpmPackageStoreInfo])
if ctx.attr.src:
+ sources_depset = depset(transitive = [jsinfo.transitive_sources for jsinfo in js_infos])
+ types_depset = depset(transitive = [jsinfo.transitive_types for jsinfo in js_infos])
for npm_package_store_info in npm_package_store_infos:
transitive_files_depsets.append(npm_package_store_info.transitive_files)
else:
@@ -360,21 +372,23 @@
# closure of all the entire package store deps, we can safely add just `files` from each of
# these to `transitive_files_depset`; doing so reduces the size of `transitive_files_depset`
# significantly and reduces analysis time and Bazel memory usage during analysis
+ sources_depset = depset(transitive = [jsinfo.sources for jsinfo in js_infos])
+ types_depset = depset(transitive = [jsinfo.types for jsinfo in js_infos])
for npm_package_store_info in npm_package_store_infos:
transitive_files_depsets.append(npm_package_store_info.files)
+ npm_sources = depset(files, transitive = [jsinfo.npm_sources for jsinfo in js_infos])
transitive_files_depset = depset(files, transitive = transitive_files_depsets)
-
files_depset = depset(files)
providers = [
js_info(
target = ctx.label,
- npm_sources = transitive_files_depset,
- ),
- DefaultInfo(
- files = files_depset,
- runfiles = ctx.runfiles(transitive_files = transitive_files_depset),
+ npm_sources = npm_sources,
+ sources = sources_depset,
+ transitive_sources = sources_depset,
+ types = types_depset,
+ transitive_types = types_depset,
),
NpmPackageStoreInfo(
root_package = ctx.label.package,