about summary refs log tree commit diff
path: root/pkgs/development/web
diff options
context:
space:
mode:
authorJaka Hudoklin <jakahudoklin@gmail.com>2014-09-09 22:46:11 +0200
committerJaka Hudoklin <jakahudoklin@gmail.com>2014-09-09 22:46:11 +0200
commit7ff4ffd998aa0a75914f1e6a905d886fb83b3419 (patch)
tree6c0bed393cb8c8b68d83fc4edfb979e1eb506248 /pkgs/development/web
parent7d6a27a78060ffb1014633e5cb9a10d5222cdb5a (diff)
downloadnixlib-7ff4ffd998aa0a75914f1e6a905d886fb83b3419.tar
nixlib-7ff4ffd998aa0a75914f1e6a905d886fb83b3419.tar.gz
nixlib-7ff4ffd998aa0a75914f1e6a905d886fb83b3419.tar.bz2
nixlib-7ff4ffd998aa0a75914f1e6a905d886fb83b3419.tar.lz
nixlib-7ff4ffd998aa0a75914f1e6a905d886fb83b3419.tar.xz
nixlib-7ff4ffd998aa0a75914f1e6a905d886fb83b3419.tar.zst
nixlib-7ff4ffd998aa0a75914f1e6a905d886fb83b3419.zip
nodePackages: add support for recursive dependencies
This is a drop-in replacement that handles nodejs recursive dependencies by
propagating already visited nodejs packages and creating shims for recursive
ones. This implementation handles both, new and old npm2nix output format.
Diffstat (limited to 'pkgs/development/web')
-rw-r--r--pkgs/development/web/nodejs/build-node-package.nix199
1 files changed, 123 insertions, 76 deletions
diff --git a/pkgs/development/web/nodejs/build-node-package.nix b/pkgs/development/web/nodejs/build-node-package.nix
index ca3439df4c46..460676324108 100644
--- a/pkgs/development/web/nodejs/build-node-package.nix
+++ b/pkgs/development/web/nodejs/build-node-package.nix
@@ -1,6 +1,6 @@
 { stdenv, runCommand, nodejs, neededNatives}:
 
-args @ { name, src, deps ? [], peerDependencies ? [], flags ? [], preShellHook ? "",  postShellHook ? "", ... }:
+args @ { name, src, deps ? {}, peerDependencies ? [], flags ? [], preShellHook ? "",  postShellHook ? "", resolvedDeps ? {}, bin ? null, ... }:
 
 with stdenv.lib;
 
@@ -12,88 +12,135 @@ let
     mv *node* $out
   '';
 
+  # Convert deps to attribute set
+  attrDeps = if isAttrs deps then deps else
+    (listToAttrs (map (dep: nameValuePair dep.name dep) deps));
+
+  # All required node modules, without already resolved dependencies
+  requiredDeps = removeAttrs attrDeps (attrNames resolvedDeps);
+
+  # Recursive dependencies that we want to avoid with shim creation
+  recursiveDeps = removeAttrs attrDeps (attrNames requiredDeps);
+
   peerDeps = listToAttrs (concatMap (dep: map (name: {
     inherit name;
     value = dep;
   }) (filter (nm: !(elem nm (args.passthru.names or []))) dep.names)) (peerDependencies));
-in
-stdenv.mkDerivation ({
-  unpackPhase = "true";
-
-  inherit src;
-
-  configurePhase = ''
-    runHook preConfigure
-    mkdir node_modules
-    ${concatStrings (concatMap (dep: map (name: ''
-      ln -sv ${dep}/lib/node_modules/${name} node_modules/
-    '') dep.names) deps)}
-    ${concatStrings (mapAttrsToList (name: dep: ''
-      ln -sv ${dep}/lib/node_modules/${name} node_modules/
-    '') peerDeps)}
-    export HOME=$(pwd)
-    runHook postConfigure
-  '';
 
-  buildPhase = ''
-    runHook preBuild
-    npm --registry http://www.example.com --nodedir=${sources} install $src ${npmFlags}
-    runHook postBuild
-  '';
+  self = let
+    # Pass resolved dependencies to dependencies of this package 
+    deps = map (
+      dep: dep.override {
+        resolvedDeps = resolvedDeps // { "${name}" = self; };
+      }
+    ) (attrValues requiredDeps);
+
+  in stdenv.mkDerivation ({
+    unpackPhase = "true";
+
+    inherit src;
+    
+    configurePhase = ''
+      runHook preConfigure
+      mkdir node_modules
+
+      # Symlink dependencies for node modules
+      ${concatStrings (concatMap (dep: map (name: ''
+        ln -sv ${dep}/lib/node_modules/${name} node_modules/
+      '') dep.names) deps)}
+
+      # Symlink peer dependencies
+      ${concatStrings (mapAttrsToList (name: dep: ''
+        ln -sv ${dep}/lib/node_modules/${name} node_modules/
+      '') peerDeps)}
+
+      # Create shims for recursive dependenceies
+      ${concatStrings (concatMap (dep: map (name: ''
+        mkdir -p node_modules/${name}
+        cat > node_modules/${name}/package.json <<EOF
+        {
+            "name": "${name}",
+            "version": "${(builtins.parseDrvName dep.name).version}"
+        }
+        EOF
+      '') dep.names) (attrValues recursiveDeps))}
 
-  installPhase = ''
-    runHook preInstall
-    mkdir -p $out/lib/node_modules
-    ${concatStrings (map (name: ''
-      mv node_modules/${name} $out/lib/node_modules
-      rm -fR $out/lib/node_modules/${name}/node_modules
-      ln -sv $out/.dependent-node-modules $out/lib/node_modules/${name}/node_modules
-      if [ -e "$out/lib/node_modules/${name}/man" ]; then
-        mkdir -p $out/share
-        for dir in "$out/lib/node_modules/${name}/man/"*; do
-          mkdir -p $out/share/man/$(basename "$dir")
-          for page in "$dir"/*; do
-            ln -sv $page $out/share/man/$(basename "$dir")
+      export HOME=$(pwd)
+      runHook postConfigure
+    '';
+
+    buildPhase = ''
+      runHook preBuild
+      npm --registry http://www.example.com --nodedir=${sources} install $src ${npmFlags}
+      runHook postBuild
+    '';
+
+    installPhase = ''
+      runHook preInstall
+
+      # Remove shims
+      ${concatStrings (concatMap (dep: map (name: ''
+        rm  node_modules/${name}/package.json
+        rmdir node_modules/${name}
+      '') dep.names) (attrValues recursiveDeps))}
+
+      mkdir -p $out/lib/node_modules
+      ${concatStrings (map (name: ''
+        mv node_modules/${name} $out/lib/node_modules
+        rm -fR $out/lib/node_modules/${name}/node_modules
+        ln -sv $out/.dependent-node-modules $out/lib/node_modules/${name}/node_modules
+        if [ -e "$out/lib/node_modules/${name}/man" ]; then
+          mkdir -p $out/share
+          for dir in "$out/lib/node_modules/${name}/man/"*; do
+            mkdir -p $out/share/man/$(basename "$dir")
+            for page in "$dir"/*; do
+              ln -sv $page $out/share/man/$(basename "$dir")
+            done
           done
-        done
+        fi
+      '') args.passthru.names)}
+      ${concatStrings (mapAttrsToList (name: dep: ''
+        mv node_modules/${name} $out/lib/node_modules
+      '') peerDeps)}
+      mv node_modules/.bin $out/lib/node_modules 2>/dev/null || true
+      mv node_modules $out/.dependent-node-modules
+      if [ -d "$out/lib/node_modules/.bin" ]; then
+        ln -sv $out/lib/node_modules/.bin $out/bin
+        node=`type -p node`
+        coffee=`type -p coffee || true`
+        find -L $out/lib/node_modules/.bin/* -type f -print0 | \
+          xargs -0 sed --follow-symlinks -i \
+            -e 's@#!/usr/bin/env node@#!'"$node"'@' \
+            -e 's@#!/usr/bin/env coffee@#!'"$coffee"'@' \
+            -e 's@#!/.*/node@#!'"$node"'@' \
+            -e 's@#!/.*/coffee@#!'"$coffee"'@'
       fi
-    '') args.passthru.names)}
-    ${concatStrings (mapAttrsToList (name: dep: ''
-      mv node_modules/${name} $out/lib/node_modules
-    '') peerDeps)}
-    mv node_modules/.bin $out/lib/node_modules 2>/dev/null || true
-    mv node_modules $out/.dependent-node-modules
-    if [ -d "$out/lib/node_modules/.bin" ]; then
-      ln -sv $out/lib/node_modules/.bin $out/bin
-      node=`type -p node`
-      coffee=`type -p coffee || true`
-      find -L $out/lib/node_modules/.bin/* -type f -print0 | \
-        xargs -0 sed --follow-symlinks -i \
-          -e 's@#!/usr/bin/env node@#!'"$node"'@' \
-          -e 's@#!/usr/bin/env coffee@#!'"$coffee"'@' \
-          -e 's@#!/.*/node@#!'"$node"'@' \
-          -e 's@#!/.*/coffee@#!'"$coffee"'@'
-    fi
-    runHook postInstall
-  '';
+      runHook postInstall
+    '';
 
-  preFixup = concatStringsSep "\n" (map (src: ''
-    find $out -type f -print0 | xargs -0 sed -i 's|${src}|${src.name}|g'
-  '') src);
-
-  shellHook = ''
-    ${preShellHook}
-    export PATH=${nodejs}/bin:$(pwd)/node_modules/.bin:$PATH
-    mkdir -p node_modules
-    ${concatStrings (concatMap (dep: map (name: ''
-      ln -sfv ${dep}/lib/node_modules/${name} node_modules/
-    '') dep.names) deps)}
-    ${postShellHook}
-  '';
-} // args // {
-  # Run the node setup hook when this package is a build input
-  propagatedNativeBuildInputs = (args.propagatedNativeBuildInputs or []) ++ [ nodejs ];
+    preFixup = concatStringsSep "\n" (map (src: ''
+      find $out -type f -print0 | xargs -0 sed -i 's|${src}|${src.name}|g'
+    '') src);
+
+    shellHook = ''
+      ${preShellHook}
+      export PATH=${nodejs}/bin:$(pwd)/node_modules/.bin:$PATH
+      mkdir -p node_modules
+      ${concatStrings (concatMap (dep: map (name: ''
+        ln -sfv ${dep}/lib/node_modules/${name} node_modules/
+      '') dep.names) deps)}
+      ${postShellHook}
+    '';
+  } // (filterAttrs (n: v: n != "deps" && n != "resolvedDeps") args) // {
+    name = "${
+      if bin == true then "bin-" else if bin == false then "node-" else ""
+    }${name}";
+
+    # Run the node setup hook when this package is a build input
+    propagatedNativeBuildInputs = (args.propagatedNativeBuildInputs or []) ++ [ nodejs ];
+
+    # Make buildNodePackage useful with --run-env
+    nativeBuildInputs = (args.nativeBuildInputs or []) ++ deps ++ peerDependencies ++ neededNatives;
+  });
 
-  # Make buildNodePackage useful with --run-env
-  nativeBuildInputs = (args.nativeBuildInputs or []) ++ deps ++ peerDependencies ++ neededNatives;
-} )
+in self