diff mbox series

[RFC,19/30] classes: add vendor class for npm

Message ID 20250211150034.18696-19-stefan.herbrechtsmeier-oss@weidmueller.com
State New
Headers show
Series Add vendor support for go, npm and rust | expand

Commit Message

Stefan Herbrechtsmeier Feb. 11, 2025, 3 p.m. UTC
From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>

Add a vendor class for npm to resolve the dependency SRC_URIs from a
package-lock.json file and populate the npm node_modules folder. The
class replaces the normal npm class and provide a simplified compile and
install task.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
---

 meta/classes-recipe/vendor_npm.bbclass | 115 +++++++++++++++++++++++++
 1 file changed, 115 insertions(+)
 create mode 100644 meta/classes-recipe/vendor_npm.bbclass
diff mbox series

Patch

diff --git a/meta/classes-recipe/vendor_npm.bbclass b/meta/classes-recipe/vendor_npm.bbclass
new file mode 100644
index 0000000000..c8bb2b6403
--- /dev/null
+++ b/meta/classes-recipe/vendor_npm.bbclass
@@ -0,0 +1,115 @@ 
+# Copyright (C) 2025 Weidmueller Interface GmbH & Co. KG
+# Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+# The directory of the package.json file relative to the root directory, per
+# default assume there's a file directly in the root directory
+NPM_SRC_DIR ?= ""
+
+# The path to the package.json file
+NPM_MANIFEST_FILE ?= "${NPM_SRC_PATH}/package.json"
+
+# The path to package-lock.json file
+NPM_LOCK_FILE ?= "${@os.path.join(os.path.dirname(d.getVar('NPM_MANIFEST_FILE')), 'package-lock.json')}"
+
+# The URL of the npm registry
+NPM_REGISTRY ?= "https://registry.npmjs.org"
+
+# The option to npm install development dependencies
+NPM_INSTALL_DEV ?= "0"
+
+# The option to npm prune development dependencies after install
+NPM_PRUNE_DEV ?= "${@['0', '1'][oe.types.boolean(d.getVar('NPM_INSTALL_DEV'))]}"
+
+# The nodejs architecture of the target
+NPM_ARCH ?= "${@map_nodejs_arch(d.getVar("TARGET_ARCH"), d)}"
+
+inherit nodejs-arch python3native vendor
+
+DEPENDS:append = "nodejs-native"
+RDEPENDS:${PN}:append:class-target = "${@['', ' nodejs'][bb.data.inherits_class('allarch', d)]}"
+
+NPM_SRC_PATH = "${S}/${NPM_SRC_DIR}"
+NPM_SRC_SUBDIR = "${@os.path.relpath(d.getVar('NPM_SRC_PATH'), d.getVar('WORKDIR'))}"
+NPM_SRC_URI_FILE = "${VENDOR_DIR}/npm-source-uris.txt"
+SRC_URI_FILES:append = " ${NPM_SRC_URI_FILE}"
+
+NPM = "npm"
+NPM_CACHE = "${WORKDIR}/cache/npm"
+NPM_COMMON_FLAGS = "\
+    --offline \
+    --fund=false \
+    --audit=false \
+    --cache=${NPM_CACHE} \
+    --loglevel=silly \
+    --foreground-scripts \
+    --release \
+    --nodedir='${RECIPE_SYSROOT_NATIVE}${prefix_native}' \
+    --python=${PYTHON} \
+    --build-from-source \
+"
+NPM_BUILD_FLAGS = "\
+    ${NPM_COMMON_FLAGS} \
+    --arch=${NPM_TARGET_ARCH} \
+    --target_arch=${NPM_TARGET_ARCH} \
+"
+
+export NPM_CONFIG_USERCONFIG = "/dev/null"
+export NPM_CONFIG_GLOBALCONFIG = "null"
+
+def npm_src_uri(d, name=None, version=None, registry=None, subdir=None):
+    import oe.vendor.npm
+    if not name:
+        name = d.getVar("PN")
+    if not version:
+        version = d.getVar("PV")
+    if not registry:
+        registry = d.getVar("NPM_REGISTRY")
+    if not subdir:
+        subdir = os.path.basename(d.getVar("S"))
+    return oe.vendor.npm.determine_src_uri(registry, name, version, subdir)
+
+python vendor_npm_do_vendor_resolve() {
+    import oe.vendor
+    import oe.vendor.npm
+
+    lock_file_dir = d.getVar("NPM_LOCK_FILE")
+    lock_file_dir = get_early_source_dir(d, lock_file_dir)
+    registry = d.getVar("NPM_REGISTRY")
+    src_subdir = d.getVar("NPM_SRC_SUBDIR")
+    dev = oe.types.boolean(d.getVar("NPM_INSTALL_DEV"))
+    src_uris = oe.vendor.npm.resolve_src_uris(lock_file_dir, registry,
+                                              src_subdir, dev)
+    with open(d.getVar("NPM_SRC_URI_FILE"), "w") as f:
+        oe.vendor.dump(f, src_uris)
+}
+
+oe_run_npm() {
+    bbnote ${NPM} "$@"
+    ${NPM} "$@"
+}
+
+vendor_npm_do_compile() {
+    oe_run_npm rebuild ${NPM_BUILD_FLAGS}
+}
+do_compile[cleandirs] += "${NPM_CACHE}"
+
+vendor_npm_do_install() {
+    oe_run_npm install --global --prefix=${D}${exec_prefix}
+    rm ${D}${exec_prefix}/lib/node_modules/${BPN}
+    install -d ${D}${exec_prefix}/lib/node_modules/${BPN}
+    tar -C . -cf - --exclude-vcs . | \
+        tar -C ${D}${exec_prefix}/lib/node_modules/${BPN} --no-same-owner -xf -
+    rm -rf ${D}${exec_prefix}/lib/node_modules/${BPN}/node_modules/.bin
+    if "${@['false', 'true'][oe.types.boolean(d.getVar('NPM_PRUNE_DEV'))]}"; then
+        (cd ${D}${exec_prefix}/lib/node_modules; oe_run_npm prune --omit=dev)
+    fi
+}
+
+FILES:${PN} += " \
+    ${nonarch_libdir}/node_modules/${BPN} \
+"
+
+EXPORT_FUNCTIONS do_vendor_resolve do_compile do_install