add devShell outputs for nodejs ad python (#186)

* add devShell outputs for nodejs ad python

* nodejs devShell improvements

- do not export NODE_PATH
- create node_modules directory
- add .bin directories of direct dependencies to PATH

* nodejs: revise devShell logic

- fix namespaced modules symlinking to ./node_modules
- add all transitive exectables to ./node_modules/.bin
- add ./node_modules/.bin to PATH

* set nodejs version in eslint example

* nodejs: improve error message on failed node_modules symlink in devShell

* readme: add nodejs version setting to example
This commit is contained in:
DavHau 2022-07-12 18:54:35 +02:00 committed by GitHub
parent 4bb76f8a1b
commit 10fecabe3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 86 additions and 2 deletions

View File

@ -77,6 +77,7 @@ Extensive Example `flake.nix`:
{ {
filter = project: project.translator == "package-json"; filter = project: project.translator == "package-json";
subsystemInfo.npmArgs = "--legacy-peer-deps"; subsystemInfo.npmArgs = "--legacy-peer-deps";
subsystemInfo.nodejs = 18;
} }
]; ];

View File

@ -17,6 +17,7 @@
settings = [ settings = [
{ {
subsystemInfo.noDev = true; subsystemInfo.noDev = true;
subsystemInfo.nodejs = 18;
} }
]; ];
}) })

View File

@ -62,7 +62,7 @@
makePackage name version)) makePackage name version))
packageVersions; packageVersions;
outputs = { outputs = rec {
# select only the packages listed in dreamLock as main packages # select only the packages listed in dreamLock as main packages
packages = packages =
b.foldl' b.foldl'
@ -73,6 +73,16 @@
"${name}"."${version}" = allPackages."${name}"."${version}"; "${name}"."${version}" = allPackages."${name}"."${version}";
}) })
args.packages); args.packages);
devShell = devShells.default;
devShells =
{default = devShells.${defaultPackageName};}
// (
l.mapAttrs
(name: version: allPackages.${name}.${version}.devShell)
args.packages
);
}; };
# This is only executed for electron based packages. # This is only executed for electron based packages.
@ -148,6 +158,8 @@
# Generates a derivation for a specific package name + version # Generates a derivation for a specific package name + version
makePackage = name: version: let makePackage = name: version: let
pname = lib.replaceStrings ["@" "/"] ["__at__" "__slash__"] name;
deps = getDependencies name version; deps = getDependencies name version;
nodeDeps = nodeDeps =
@ -155,6 +167,35 @@
deps deps
(dep: allPackages."${dep.name}"."${dep.version}"); (dep: allPackages."${dep.name}"."${dep.version}");
# Derivation building the ./node_modules directory in isolation.
# This is used for the devShell of the current package.
# We do not want to build the full package for the devShell.
nodeModulesDir = pkgs.runCommand "node_modules-${pname}" {} ''
# symlink direct dependencies to ./node_modules
mkdir $out
${l.concatStringsSep "\n" (
l.forEach nodeDeps
(pkg: ''
for dir in $(ls ${pkg}/lib/node_modules/); do
if [[ $dir == @* ]]; then
mkdir -p $out/$dir
ln -s ${pkg}/lib/node_modules/$dir/* $out/$dir/
else
ln -s ${pkg}/lib/node_modules/$dir $out/
fi
done
'')
)}
# symlink transitive executables to ./node_modules/.bin
mkdir $out/.bin
for dep in ${l.toString nodeDeps}; do
for binDir in $(ls -d $dep/lib/node_modules/.bin 2>/dev/null ||:); do
ln -sf $binDir/* $out/.bin/
done
done
'';
passthruDeps = passthruDeps =
l.listToAttrs l.listToAttrs
(l.forEach deps (l.forEach deps
@ -198,10 +239,27 @@
packageName = name; packageName = name;
pname = lib.replaceStrings ["@" "/"] ["__at__" "__slash__"] name; inherit pname;
passthru.dependencies = passthruDeps; passthru.dependencies = passthruDeps;
passthru.devShell = pkgs.mkShell {
buildInputs = [
nodejs
];
shellHook = ''
# create the ./node_modules directory
if [ -e ./node_modules ] && [ ! -L ./node_modules ]; then
echo -e "\nFailed creating the ./node_modules symlink to ${nodeModulesDir}"
echo -e "\n./node_modules already exists and is a directory, which means it is managed by another program. Please delete ./node_modules first and re-enter the dev shell."
else
rm -f ./node_modules
ln -s ${nodeModulesDir} ./node_modules
export PATH="$PATH:$(realpath ./node_modules)/.bin"
fi
'';
};
installMethod = "symlink"; installMethod = "symlink";
electronAppDir = "."; electronAppDir = ".";
@ -421,6 +479,17 @@
ln -s $nodeModules/.bin $out/bin ln -s $nodeModules/.bin $out/bin
fi fi
echo "Symlinking transitive executables to $nodeModules/.bin"
echo "node deps: ${l.toString nodeDeps}"
for dep in ${l.toString nodeDeps}; do
echo "bin dirs: $(ls -d $dep/lib/node_modules/.bin 2>/dev/null ||:)"
for binDir in $(ls -d $dep/lib/node_modules/.bin 2>/dev/null ||:); do
echo binDir $binDir
mkdir -p $nodeModules/.bin
ln -sf $binDir/* $nodeModules/.bin/
done
done
echo "Symlinking manual pages" echo "Symlinking manual pages"
if [ -d "$nodeModules/$packageName/man" ] if [ -d "$nodeModules/$packageName/man" ]
then then

View File

@ -66,7 +66,20 @@
$pipInstallFlags $pipInstallFlags
''; '';
}); });
devShell = pkgs.mkShell {
buildInputs = [
# a drv with all dependencies without the main package
(package.overrideAttrs (old: {
src = ".";
dontUnpack = true;
buildPhase = old.preBuild;
}))
];
};
in { in {
packages.${defaultPackageName}.${defaultPackageVersion} = package; packages.${defaultPackageName}.${defaultPackageVersion} = package;
devShells.${defaultPackageName} = devShell;
inherit devShell;
}; };
} }