summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--guix/build/node-build-system.scm51
-rw-r--r--tests/node.scm99
3 files changed, 141 insertions, 10 deletions
diff --git a/Makefile.am b/Makefile.am
index b8fc38c6f37..26ee98d55c8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -602,6 +602,7 @@ SCM_TESTS = \
602 tests/monads.scm \ 602 tests/monads.scm \
603 tests/nar.scm \ 603 tests/nar.scm \
604 tests/networking.scm \ 604 tests/networking.scm \
605 tests/node.scm \
605 tests/openpgp.scm \ 606 tests/openpgp.scm \
606 tests/packages.scm \ 607 tests/packages.scm \
607 tests/pack.scm \ 608 tests/pack.scm \
diff --git a/guix/build/node-build-system.scm b/guix/build/node-build-system.scm
index 60c01094a92..ac7af1a016d 100644
--- a/guix/build/node-build-system.scm
+++ b/guix/build/node-build-system.scm
@@ -36,7 +36,9 @@
36 #:use-module (srfi srfi-71) 36 #:use-module (srfi srfi-71)
37 #:export (%standard-phases 37 #:export (%standard-phases
38 delete-dependencies 38 delete-dependencies
39 delete-dependencies/except
39 delete-dev-dependencies 40 delete-dev-dependencies
41 delete-dev-dependencies/except
40 delete-fields 42 delete-fields
41 add-fields 43 add-fields
42 modify-json 44 modify-json
@@ -74,26 +76,55 @@ a value to be written as JSON to the replacement FILE."
74 modifications)) 76 modifications))
75 file))) 77 file)))
76 78
77(define (delete-dependencies dependencies-to-remove) 79(define %dependency-keys
80 '("devDependencies"
81 "dependencies"
82 "peerDependencies"
83 "optionalDependencies"))
84
85(define %dev-dependency-keys
86 '("devDependencies"
87 "peerDependencies"))
88
89(define* (delete-dependencies dependencies-to-remove
90 #:key negate?
91 (dependency-keys %dependency-keys))
78 "Rewrite 'package.json' to allow the build to proceed without packages 92 "Rewrite 'package.json' to allow the build to proceed without packages
79listed in 'dependencies-to-remove', a list of strings naming npm packages. 93listed in 'dependencies-to-remove', a list of strings naming npm packages. To
94negate its effect, and keep DEPENDENCIES-TO-REMOVE instead of removing them,
95set NEGATE? to #t. DEPENDENCY-KEYS can be used to adjust which dependency
96fields are targeted.
80 97
81To prevent the deleted dependencies from being reintroduced, use this function 98To prevent the deleted dependencies from being reintroduced, use this function
82only after the 'patch-dependencies' phase." 99only after the 'patch-dependencies' phase."
83 (let ((predicate (lambda (dependency) 100 (let ((predicate (lambda (dependency)
84 (member (car dependency) dependencies-to-remove))) 101 (member (car dependency) dependencies-to-remove)))
85 (dependency? (cut member <> (list "devDependencies" 102 (dependency? (cut member <> %dependency-keys)))
86 "dependencies"
87 "peerDependencies"
88 "optionalDependencies"))))
89 (lambda (pkg-meta) 103 (lambda (pkg-meta)
90 (map (match-lambda 104 (map (match-lambda
91 (((? dependency? key) . dependencies) 105 (((? dependency? key) . dependencies)
92 (cons key (remove predicate dependencies))) 106 (let* (((values removed kept)
93 (otherwise 107 (partition ((if negate? negate identity)
94 otherwise)) 108 predicate)
109 dependencies)))
110 (format #t "deleting ~s dependencies: ~y~%" key removed)
111 (cons key kept)))
112 (otherwise otherwise))
95 pkg-meta)))) 113 pkg-meta))))
96 114
115(define* (delete-dependencies/except dependencies-to-preserve
116 #:key (dependency-keys %dependency-keys))
117 "Like `delete-dependencies', but deleting all dependencies except those
118listed in DEPENDENCIES-TO-PRESERVE."
119 (delete-dependencies dependencies-to-preserve #:negate? #t
120 #:dependency-keys dependency-keys))
121
122(define* (delete-dev-dependencies/except dependencies-to-preserve)
123 "Like `delete-dependencies/except' but only acting on development
124dependencies."
125 (delete-dependencies/except dependencies-to-preserve
126 #:dependency-keys %dev-dependency-keys))
127
97(define* (modify-json-fields fields field-modifier 128(define* (modify-json-fields fields field-modifier
98 #:key 129 #:key
99 (field-path-mapper identity) 130 (field-path-mapper identity)
@@ -175,7 +206,7 @@ invalid field value provided, expected string or list of strings, got ~s~%"
175 fields 206 fields
176 (lambda (field data key) 207 (lambda (field data key)
177 (let ((value (cdr field))) 208 (let ((value (cdr field)))
178 (format #t "setting field ~s to value ~s%" key value) 209 (format #t "setting field ~s to value: ~y~%" key value)
179 (assoc-set! data key value))) 210 (assoc-set! data key value)))
180 #:field-path-mapper (lambda (field) (car field)) 211 #:field-path-mapper (lambda (field) (car field))
181 #:insert? insert? 212 #:insert? insert?
diff --git a/tests/node.scm b/tests/node.scm
new file mode 100644
index 00000000000..5159d530a12
--- /dev/null
+++ b/tests/node.scm
@@ -0,0 +1,99 @@
1;;; GNU Guix --- Tests for the node-build-system procedures.
2;;; Copyright © 2026 Maxim Cournoyer <maxim@guixotic.coop>
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(use-modules (json)
20 (guix build node-build-system)
21 (guix tests)
22 (srfi srfi-64))
23
24(define (package.json)
25 "Sample package.json file."
26 (call-with-output-string
27 (lambda (out)
28 (scm->json
29 '(("devDependencies"
30 ("typescript-eslint" . "^8.61.0")
31 ("typescript" . "^5.9.3")
32 ("typedoc" . "^0.28.19")
33 ("htmlparser2" . "^10.1.0")
34 ("eslint" . "^10.4.1")
35 ("@types/node" . "^25.9.2"))
36 ("dependencies"
37 ("domelementtype" . "^3.0.0")
38 ("boolbase" . ">=2.0.0"))
39 ("peerDependencies"
40 ("mkdirp" . ">=1.0.0")
41 ("react" . "^16.8.0"))
42 ("engines" ("node" . ">=20.19.0"))
43 ("repository"
44 ("url" . "https://example.com/dummy/dummy.git")
45 ("type" . "git"))
46 ("scripts"
47 ("test" . "npm run test")
48 ("lint" . "eslint .")
49 ("build" . "tsc"))
50 ("files" . #("dist" "src" "!**/*.spec.ts"))
51 ("sideEffects" . #f)
52 ("exports"
53 ("." ("default" . "./dist/index.js") ("types" . "./dist/index.d.ts")))
54 ("types" . "dist/index.d.ts")
55 ("main" . "dist/index.js")
56 ("license" . "GPL-3.0")
57 ("description" . "Dummy package.json")
58 ("version" . "6.0.1")
59 ("name" . "dummy")
60 ("type" . "module"))
61 out #:pretty #t))))
62
63(define* (modify-json* #:rest all-arguments)
64 "Wrap modify-json to use our package.json test sample and avoid file I/O.
65It also returns the data as an alist directly."
66 (mock ((guix build utils) with-atomic-file-replacement
67 (lambda (_ proc)
68 (call-with-input-string (package.json)
69 (lambda (in)
70 (call-with-output-string
71 (lambda (out)
72 (proc in out)))))))
73 (json-string->scm (apply modify-json all-arguments)
74 #:ordered #t)))
75
76
77(test-begin "node related tests")
78
79(test-equal "delete-dependencies"
80 '(("domelementtype" . "^3.0.0"))
81 (assoc-ref (modify-json*
82 (delete-dependencies '("boolbase")))
83 "dependencies"))
84
85(test-equal "delete-dependencies/except"
86 '(("boolbase" . ">=2.0.0"))
87 (assoc-ref (modify-json*
88 (delete-dependencies/except '("boolbase")))
89 "dependencies"))
90
91(test-equal "delete-dev-dependencies/except"
92 '(("@types/node" . "^25.9.2")
93 ("typescript" . "^5.9.3"))
94 (assoc-ref (modify-json*
95 (delete-dev-dependencies/except
96 '("typescript" "@types/node")))
97 "devDependencies"))
98
99(test-end)