Merge pull request #4018 from offlinehacker/npm_recursive

nodePackages: add support for recursive dependencies
This commit is contained in:
Sander van der Burg 2014-09-11 12:16:22 +02:00
commit 550ef760eb

View File

@ -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,12 +12,30 @@ 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 ({
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;
@ -25,12 +43,28 @@ stdenv.mkDerivation ({
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))}
export HOME=$(pwd)
runHook postConfigure
'';
@ -43,6 +77,13 @@ stdenv.mkDerivation ({
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
@ -90,10 +131,16 @@ stdenv.mkDerivation ({
'') dep.names) deps)}
${postShellHook}
'';
} // args // {
} // (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;
} )
});
in self