diff options
| -rw-r--r-- | Makefile.am | 1 | ||||
| -rw-r--r-- | guix/build/node-build-system.scm | 51 | ||||
| -rw-r--r-- | tests/node.scm | 99 |
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 |
| 79 | listed in 'dependencies-to-remove', a list of strings naming npm packages. | 93 | listed in 'dependencies-to-remove', a list of strings naming npm packages. To |
| 94 | negate its effect, and keep DEPENDENCIES-TO-REMOVE instead of removing them, | ||
| 95 | set NEGATE? to #t. DEPENDENCY-KEYS can be used to adjust which dependency | ||
| 96 | fields are targeted. | ||
| 80 | 97 | ||
| 81 | To prevent the deleted dependencies from being reintroduced, use this function | 98 | To prevent the deleted dependencies from being reintroduced, use this function |
| 82 | only after the 'patch-dependencies' phase." | 99 | only 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 | ||
| 118 | listed 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 | ||
| 124 | dependencies." | ||
| 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. | ||
| 65 | It 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) | ||
