1- { nodejs-14_x , jq , openssl , stdenv , mkShell , lib , fetchurl , writeText , writeTextFile , runCommand , fetchFromGitHub } :
1+ { util , nodejs-14_x , jq , openssl , stdenv , mkShell , lib , fetchurl , writeText , writeTextFile , runCommand , fetchFromGitHub } :
22rec {
33 # Versions >= 15 use npm >= 7, which uses npm lockfile version 2, which we don't support yet
44 # See the assertion in the node_modules function
55 default_nodejs = nodejs-14_x ;
66
7-
8- # builtins.fetchGit wrapper that ensures compatibility with Nix 2.3 and Nix 2.4
9- # Type: Attrset -> Path
10- fetchGitWrapped =
11- let
12- is24OrNewer = lib . versionAtLeast builtins . nixVersion "2.4" ;
13- in
14- if is24OrNewer then
15- # remove the now unsupported / insufficient `ref` paramter
16- args : builtins . fetchGit ( builtins . removeAttrs args [ "ref" ] )
17- else
18- # for 2.3 (and older?) we remove the unsupported `allRefs` parameter
19- args : builtins . fetchGit ( builtins . removeAttrs args [ "allRefs" ] )
20- ;
21-
22- # Description: Custom throw function that ensures our error messages have a common prefix.
23- # Type: String -> Throw
24- throw = str : builtins . throw "[npmlock2nix] ${ str } " ;
25-
267 # Description: Turns an npm lockfile dependency into an attribute set as needed by fetchurl
278 # Type: String -> Set -> Set
289 makeSourceAttrs = name : dependency :
29- assert ! ( dependency ? resolved ) -> throw "Missing `resolved` attribute for dependency `${ name } `." ;
30- assert ! ( dependency ? integrity ) -> throw "Missing `integrity` attribute for dependency `${ name } `." ;
10+ assert ! ( dependency ? resolved ) -> util . throw "Missing `resolved` attribute for dependency `${ name } `." ;
11+ assert ! ( dependency ? integrity ) -> util . throw "Missing `integrity` attribute for dependency `${ name } `." ;
3112 {
3213 url = dependency . resolved ;
3314 # FIXME: for backwards compatibility we should probably set the
@@ -49,44 +30,14 @@ rec {
4930 parts = builtins . split "[:#/]" str ;
5031 in
5132 assert ! ( builtins . length parts == 7 ) ->
52- throw "failed to parse GitHub reference `${ str } `. Expected a string of format `github:org/repo#revision`" ;
33+ util . throw "failed to parse GitHub reference `${ str } `. Expected a string of format `github:org/repo#revision`" ;
5334 rec {
5435 inherit parts ;
5536 org = builtins . elemAt parts 2 ;
5637 repo = builtins . elemAt parts 4 ;
5738 rev = builtins . elemAt parts 6 ;
5839 } ;
5940
60- # Description: Takes an attribute set describing a git dependency and returns
61- # a .tgz of the repository as store path. If the attribute hash contains a
62- # hash attribute it will provide the value to `fetchFromGitHub` which will
63- # also work in restricted evaluation.
64- # Type: Set -> Path
65- buildTgzFromGitHub = { name , org , repo , rev , ref , hash ? null , sourceOptions ? { } } :
66- let
67- src =
68- if hash != null then
69- fetchFromGitHub
70- {
71- owner = org ;
72- inherit repo ;
73- inherit rev ;
74- sha256 = hash ; # FIXME: what if sha3?
75- } else
76- fetchGitWrapped {
77- url = "https://github.com/${ org } /${ repo } " ;
78- inherit rev ref ;
79- allRefs = true ;
80- } ;
81-
82- sourceInfo = {
83- github = { inherit org repo rev ref ; } ;
84- } ;
85- drv = packTgz sourceOptions . nodejs name ref src ;
86- in
87- if sourceOptions ? sourceOverrides . ${ name }
88- then sourceOptions . sourceOverrides . ${ name } sourceInfo drv
89- else drv ;
9041
9142 # Description: Packs a source directory into a .tgz tar archive. If the
9243 # source is an archive, it gets unpacked first.
@@ -120,16 +71,17 @@ rec {
12071 v = parseGitHubRef dependency . version ;
12172 f = parseGitHubRef dependency . from ;
12273 in
123- assert v . org != f . org -> throw "version and from of `${ name } ` disagree on the GitHub org to fetch from: `${ v . org } ` vs `${ f . org } `" ;
124- assert v . repo != f . repo -> throw "version and from of `${ name } ` disagree on the GitHub repo to fetch from: `${ v . repo } ` vs `${ f . repo } `" ;
125- assert ! isGitRev v . rev -> throw "version of `${ name } ` does not specify a valid git rev: `${ v . rev } `" ;
74+ assert v . org != f . org -> util . throw "version and from of `${ name } ` disagree on the GitHub org to fetch from: `${ v . org } ` vs `${ f . org } `" ;
75+ assert v . repo != f . repo -> util . throw "version and from of `${ name } ` disagree on the GitHub repo to fetch from: `${ v . repo } ` vs `${ f . repo } `" ;
76+ assert ! isGitRev v . rev -> util . throw "version of `${ name } ` does not specify a valid git rev: `${ v . rev } `" ;
12677 let
127- src = buildTgzFromGitHub {
78+ src = util . buildTgzFromGitHub {
12879 name = "${ name } .tgz" ;
12980 ref = f . rev ;
13081 inherit ( v ) org repo rev ;
13182 hash = sourceHashFunc { type = "github" ; value = v ; } ;
13283 inherit sourceOptions ;
84+ pack = packTgz ;
13385 } ;
13486 in
13587 ( builtins . removeAttrs dependency [ "from" ] ) // {
13991 # Description: Checks if the given string looks like a vila HTTP or HTTPS url
14092 # Type: String -> Bool
14193 looksLikeUrl = s :
142- assert ( builtins . typeOf s != "string" ) -> throw "can only check strings if they are URL-like" ;
94+ assert ( builtins . typeOf s != "string" ) -> util . throw "can only check strings if they are URL-like" ;
14395 lib . hasPrefix "http://" s || lib . hasPrefix "https://" s ;
14496
14597 # Description: Checks the given dependency spec if its version field should
@@ -179,16 +131,16 @@ rec {
179131 # Type: { sourceHashFunc :: Fn } -> String -> Set -> Derivation
180132 makeSource = sourceOptions : name : dependency :
181133 assert ( builtins . typeOf name != "string" ) ->
182- throw "Name of dependency ${ toString name } must be a string" ;
134+ util . throw "Name of dependency ${ toString name } must be a string" ;
183135 assert ( builtins . typeOf dependency != "set" ) ->
184- throw "Specification of dependency ${ toString name } must be a set" ;
136+ util . throw "Specification of dependency ${ toString name } must be a set" ;
185137 if dependency ? resolved && dependency ? integrity then
186138 makeUrlSource sourceOptions name dependency
187139 else if dependency ? from && dependency ? version then
188140 makeGithubSource sourceOptions name dependency
189141 else if shouldUseVersionAsUrl dependency then
190142 makeSource sourceOptions name ( dependency // { resolved = dependency . version ; } )
191- else throw "A valid dependency consists of at least the resolved and integrity field. Missing one or both of them for `${ name } `. The object I got looks like this: ${ builtins . toJSON dependency } " ;
143+ else util . throw "A valid dependency consists of at least the resolved and integrity field. Missing one or both of them for `${ name } `. The object I got looks like this: ${ builtins . toJSON dependency } " ;
192144
193145 # Description: Parses the lock file as json and returns an attribute set
194146 # Type: Path -> Set
@@ -199,7 +151,7 @@ rec {
199151 in
200152 assert
201153 builtins . typeOf json != "set" ->
202- throw "The NPM lockfile must be a valid JSON object" ;
154+ util . throw "The NPM lockfile must be a valid JSON object" ;
203155 # if a lockfile doesn't declare dependencies ensure that we have an empty
204156 # set. This makes the consuming code eaiser.
205157 if json ? dependencies then json else json // { dependencies = { } ; } ;
@@ -210,12 +162,13 @@ rec {
210162 let
211163 gitAttrs = parseGitHubRef str ;
212164 in
213- buildTgzFromGitHub {
165+ util . buildTgzFromGitHub {
214166 name = "${ name } .tgz" ;
215167 ref = gitAttrs . rev ;
216168 inherit ( gitAttrs ) org repo rev ;
217169 hash = sourceHashFunc { type = "github" ; value = gitAttrs ; } ;
218170 inherit sourceOptions ;
171+ pack = packTgz ;
219172 } ;
220173
221174 # Description: Patch the `requires` attributes of a dependency spec to refer to paths in the store
@@ -231,9 +184,9 @@ rec {
231184 # Type: List String -> { sourceHashFunc :: Fn } -> String -> Set -> { result :: Set, integrityUpdates :: List { path, file } }
232185 patchDependency = path : sourceOptions : name : spec :
233186 assert ( builtins . typeOf name != "string" ) ->
234- throw "Name of dependency ${ toString name } must be a string" ;
187+ util . throw "Name of dependency ${ toString name } must be a string" ;
235188 assert ( builtins . typeOf spec != "set" ) ->
236- throw "spec of dependency ${ toString name } must be a set" ;
189+ util . throw "spec of dependency ${ toString name } must be a set" ;
237190 let
238191 isBundled = spec ? bundled && spec . bundled == true ;
239192 hasGitHubRequires = spec : ( spec ? requires ) && ( lib . any ( x : lib . hasPrefix "github:" x ) ( lib . attrValues spec . requires ) ) ;
@@ -261,7 +214,7 @@ rec {
261214 # Type: { sourceHashFunc :: Fn } -> Path -> { result :: Set, integrityUpdates :: List { path, file } }
262215 patchLockfile = sourceOptions : file :
263216 assert ( builtins . typeOf file != "path" && builtins . typeOf file != "string" ) ->
264- throw "file ${ toString file } must be a path or string" ;
217+ util . throw "file ${ toString file } must be a path or string" ;
265218 let
266219 content = readLockfile file ;
267220 dependencies = lib . mapAttrs ( name : patchDependency [ name ] sourceOptions name ) content . dependencies ;
@@ -277,7 +230,7 @@ rec {
277230 # Type: Path -> Set
278231 patchPackagefile = file :
279232 assert ( builtins . typeOf file != "path" && builtins . typeOf file != "string" ) ->
280- throw "file ${ toString file } must be a path or string" ;
233+ util . throw "file ${ toString file } must be a path or string" ;
281234 let
282235 # Read the file but also add empty `devDependencies` and `dependencies`
283236 # if either are missing
@@ -315,51 +268,7 @@ rec {
315268 integrityUpdates = patched . integrityUpdates ;
316269 } ;
317270
318- # Description: Turn a derivation (with name & src attribute) into a directory containing the unpacked sources
319- # Type: Derivation -> Derivation
320- nodeSource = nodejs : runCommand "node-sources-${ nodejs . version } "
321- { } ''
322- tar --no-same-owner --no-same-permissions -xf ${ nodejs . src }
323- mv node-* $out
324- '' ;
325-
326- # Description: Creates shell scripts to provide node_modules to the environment supporting
327- # two different modes: "symlink" and "copy"
328- # Type: Derivation -> String -> String
329- add_node_modules_to_cwd = node_modules : mode :
330- ''
331- # If node_modules is a managed symlink we can safely remove it and install a new one
332- ${ lib . optionalString ( mode == "symlink" ) ''
333- if [[ "$(readlink -f node_modules)" == ${ builtins . storeDir } * ]]; then
334- rm -f node_modules
335- fi
336- '' }
337- if test -e node_modules; then
338- echo '[npmlock2nix] There is already a `node_modules` directory. Not replacing it.' >&2
339- exit 1
340- fi
341- '' +
342- (
343- if mode == "copy" then ''
344- cp --no-preserve=mode -r ${ node_modules } /node_modules node_modules
345- chmod -R u+rw node_modules
346- '' else if mode == "symlink" then ''
347- ln -s ${ node_modules } /node_modules node_modules
348- '' else throw "node_modules_mode must be either `copy` or `symlink`"
349- ) + ''
350- export NODE_PATH="$(pwd)/node_modules:$NODE_PATH"
351- '' ;
352271
353- # Description: Extract the attributes that are relevant for building node_modules and use
354- # them as defaults in case the node_modules_attrs attribute doesn't have
355- # them.
356- # Type: Set -> Set
357- get_node_modules_attrs = { node_modules_attrs ? { } , ... } @attrs :
358- let
359- getAttr = name : from : lib . optionalAttrs ( builtins . hasAttr name from ) { "${ name } " = from . ${ name } ; } ;
360- getAttrs = names : from : lib . foldl ( a : b : a // ( getAttr b from ) ) { } names ;
361- in
362- ( getAttrs [ "src" "nodejs" ] attrs // node_modules_attrs ) ;
363272
364273 # Description: Takes a dependency spec and a map of github sources/hashes and returns either the map or 'null'
365274 # Type: Set -> Set -> Set | null
@@ -374,7 +283,7 @@ rec {
374283 )
375284 githubSourceHashMap
376285 else
377- throw "sourceHashFunc: spec.type '${ spec . type } ' is not supported. Supported types: 'github'" ;
286+ util . throw "sourceHashFunc: spec.type '${ spec . type } ' is not supported. Supported types: 'github'" ;
378287
379288 node_modules =
380289 { src
@@ -392,9 +301,9 @@ rec {
392301 , ...
393302 } @args :
394303 assert lib . versionAtLeast nodejs . version "15.0" ->
395- throw "npmlock2nix is called with nodejs version ${ nodejs . version } , which is currently not supported, see https://github.com/nix-community/npmlock2nix/issues/153 for more information" ;
304+ util . throw "npmlock2nix is called with nodejs version ${ nodejs . version } , which is currently not supported, see https://github.com/nix-community/npmlock2nix/issues/153 for more information" ;
396305 assert ( builtins . typeOf preInstallLinks != "set" ) ->
397- throw "`preInstallLinks` must be an attributeset of attributesets" ;
306+ util . throw "`preInstallLinks` must be an attributeset of attributesets" ;
398307 let
399308 cleanArgs = builtins . removeAttrs args [ "src" "packageJson" "packageLockJson" "buildInputs" "nativeBuildInputs" "nodejs" "preBuild" "postBuild" "preInstallLinks" "sourceOverrides" "githubSourceHashMap" ] ;
400309 lockfile = readLockfile packageLockJson ;
@@ -506,7 +415,7 @@ rec {
506415 declare -pf > $TMP/preinstall-env
507416 ln -s ${ preinstall_node_modules } /node_modules/.hooks/prepare node_modules/.hooks/preinstall
508417 export HOME=.
509- npm install --offline --nodedir=${ nodeSource nodejs }
418+ npm install --offline --nodedir=${ util . nodeSource nodejs }
510419 test -d node_modules/.bin && patchShebangs node_modules/.bin
511420 rm -rf node_modules/.hooks
512421 runHook postBuild
@@ -540,14 +449,14 @@ rec {
540449 , ...
541450 } @attrs :
542451 let
543- nm = node_modules ( get_node_modules_attrs attrs ) ;
452+ nm = node_modules ( util . get_node_modules_attrs attrs ) ;
544453 extraAttrs = builtins . removeAttrs attrs [ "node_modules_attrs" "passthru" "shellHook" "buildInputs" ] ;
545454 in
546455 mkShell ( {
547456 buildInputs = buildInputs ++ [ nm . nodejs nm ] ;
548457 shellHook = ''
549458 # FIXME: we should somehow register a GC root here in case of a symlink?
550- ${ add_node_modules_to_cwd nm node_modules_mode }
459+ ${ util . add_node_modules_to_cwd nm node_modules_mode }
551460 '' + shellHook ;
552461 passthru = passthru // {
553462 node_modules = nm ;
@@ -565,7 +474,7 @@ rec {
565474 , ...
566475 } @attrs :
567476 let
568- nm = node_modules ( get_node_modules_attrs attrs ) ;
477+ nm = node_modules ( util . get_node_modules_attrs attrs ) ;
569478 extraAttrs = builtins . removeAttrs attrs [ "node_modules_attrs" "passthru" "buildInputs" ] ;
570479 in
571480 stdenv . mkDerivation ( {
@@ -574,7 +483,7 @@ rec {
574483 buildInputs = [ nm ] ++ buildInputs ;
575484 inherit src installPhase ;
576485
577- preConfigure = add_node_modules_to_cwd nm node_modules_mode ;
486+ preConfigure = util . add_node_modules_to_cwd nm node_modules_mode ;
578487
579488 buildPhase = ''
580489 runHook preBuild
0 commit comments