@@ -49,6 +49,7 @@ (define (default-node)
(define* (lower name
#:key source inputs native-inputs outputs system target
(node (default-node))
+ (absent-dependencies ''())
#:allow-other-keys
#:rest arguments)
"Return a bag for NAME."
@@ -84,6 +85,7 @@ (define* (node-build name inputs
(test-target "test")
(tests? #t)
(phases '%standard-phases)
+ (absent-dependencies ''())
(outputs '("out"))
(search-paths '())
(system (%current-system))
@@ -91,7 +93,21 @@ (define* (node-build name inputs
(imported-modules %node-build-system-modules)
(modules '((guix build node-build-system)
(guix build utils))))
- "Build SOURCE using NODE and INPUTS."
+ "Build SOURCE using NODE and INPUTS.
+
+The builder will remove Node.js packages listed in ABSENT-DEPENCENCIES from
+the 'package.json' file's 'dependencies' and 'devDependencies' tables. This
+mechanism can be used both avoid dependencies we don't want (e.g. optional
+features that would increase closure size) and to work around dependencies
+that haven't been packaged for Guix yet (e.g. test utilities)."
+ ;; Before #:absent-dependencies existed, this scenario was often handled by
+ ;; deleting the 'configure phase. Using #:absent-dependencies, instead,
+ ;; retains the check that no dependencies are silently missing and other
+ ;; actions performed by 'npm install', such as building native
+ ;; addons. Having an explicit list of absent dependencies in the package
+ ;; definition should also facilitate future maintenence: for example, if we
+ ;; add a package for a test framework, it should be easy to find all the
+ ;; other packages that use it and enable their tests.
(define builder
(with-imported-modules imported-modules
#~(begin
@@ -103,6 +119,7 @@ (define builder
#:test-target #$test-target
#:tests? #$tests?
#:phases #$phases
+ #:absent-dependencies #$absent-dependencies
#:outputs #$(outputs->gexp outputs)
#:search-paths '#$(sexp->gexp
(map search-path-specification->sexp
@@ -325,6 +325,22 @@ (define resolve-dependencies
deps))))))
#t)
+(define* (delete-dependencies #:key absent-dependencies #:allow-other-keys)
+ "Modify 'package.json' to allow building without the ABSENT-DEPENDENCIES."
+ (define delete-fom-jsobject
+ (match-lambda
+ (('@ . alist)
+ (cons '@ (filter (match-lambda
+ ((k . v)
+ (not (member k absent-dependencies))))
+ alist)))))
+ (with-atomic-json-file-replacement "package.json"
+ (lambda (pkg-meta)
+ (jsobject-update*
+ pkg-meta
+ "devDependencies" '(@) delete-fom-jsobject
+ "dependencies" '(@) delete-fom-jsobject))))
+
(define* (delete-lockfiles #:key inputs #:allow-other-keys)
"Delete 'package-lock.json', 'yarn.lock', and 'npm-shrinkwrap.json', if they
exist."
@@ -431,7 +447,8 @@ (define %standard-phases
(modify-phases gnu:%standard-phases
(add-after 'unpack 'set-home set-home)
(add-before 'configure 'patch-dependencies patch-dependencies)
- (add-after 'patch-dependencies 'delete-lockfiles delete-lockfiles)
+ (add-after 'patch-dependencies 'delete-dependencies delete-dependencies)
+ (add-after 'delete-dependencies 'delete-lockfiles delete-lockfiles)
(replace 'configure configure)
(replace 'build build)
(replace 'check check)