-
-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
1,635 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
{ lib, stdenv, fetchNpmDeps, npmHooks, nodejs }: | ||
|
||
{ name ? "${args.pname}-${args.version}" | ||
, src ? null | ||
, srcs ? null | ||
, sourceRoot ? null | ||
, patches ? [ ] | ||
, nativeBuildInputs ? [ ] | ||
, buildInputs ? [ ] | ||
# The output hash of the dependencies for this project. | ||
# Can be calculated in advance with prefetch-npm-deps. | ||
, npmDepsHash ? "" | ||
# Whether to make the cache writable prior to installing dependencies. | ||
# Don't set this unless npm tries to write to the cache directory, as it can slow down the build. | ||
, makeCacheWritable ? false | ||
# The script to run to build the project. | ||
, npmBuildScript ? "build" | ||
# Flags to pass to all npm commands. | ||
, npmFlags ? [ ] | ||
# Flags to pass to `npm ci`. | ||
, npmInstallFlags ? [ ] | ||
# Flags to pass to `npm rebuild`. | ||
, npmRebuildFlags ? [ ] | ||
# Flags to pass to `npm run ${npmBuildScript}`. | ||
, npmBuildFlags ? [ ] | ||
# Flags to pass to `npm pack`. | ||
, npmPackFlags ? [ ] | ||
, ... | ||
} @ args: | ||
|
||
let | ||
npmDeps = fetchNpmDeps { | ||
inherit src srcs sourceRoot patches; | ||
name = "${name}-npm-deps"; | ||
hash = npmDepsHash; | ||
}; | ||
|
||
inherit (npmHooks.override { inherit nodejs; }) npmConfigHook npmBuildHook npmInstallHook; | ||
in | ||
stdenv.mkDerivation (args // { | ||
inherit npmDeps npmBuildScript; | ||
|
||
nativeBuildInputs = nativeBuildInputs ++ [ nodejs npmConfigHook npmBuildHook npmInstallHook ]; | ||
buildInputs = buildInputs ++ [ nodejs ]; | ||
|
||
strictDeps = true; | ||
|
||
# Stripping takes way too long with the amount of files required by a typical Node.js project. | ||
dontStrip = args.dontStrip or true; | ||
|
||
passthru = { inherit npmDeps; } // (args.passthru or { }); | ||
|
||
meta = (args.meta or { }) // { platforms = args.meta.platforms or nodejs.meta.platforms; }; | ||
}) |
35 changes: 35 additions & 0 deletions
35
pkgs/build-support/node/build-npm-package/hooks/default.nix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ lib, makeSetupHook, nodejs, srcOnly, diffutils, jq, makeWrapper }: | ||
|
||
{ | ||
npmConfigHook = makeSetupHook | ||
{ | ||
name = "npm-config-hook"; | ||
substitutions = { | ||
nodeSrc = srcOnly nodejs; | ||
|
||
# Specify the stdenv's `diff` and `jq` by abspath to ensure that the user's build | ||
# inputs do not cause us to find the wrong binaries. | ||
# The `.nativeDrv` stanza works like nativeBuildInputs and ensures cross-compiling has the right version available. | ||
diff = "${diffutils.nativeDrv or diffutils}/bin/diff"; | ||
jq = "${jq.nativeDrv or jq}/bin/jq"; | ||
|
||
nodeVersion = nodejs.version; | ||
nodeVersionMajor = lib.versions.major nodejs.version; | ||
}; | ||
} ./npm-config-hook.sh; | ||
|
||
npmBuildHook = makeSetupHook | ||
{ | ||
name = "npm-build-hook"; | ||
} ./npm-build-hook.sh; | ||
|
||
npmInstallHook = makeSetupHook | ||
{ | ||
name = "npm-install-hook"; | ||
deps = [ makeWrapper ]; | ||
substitutions = { | ||
hostNode = "${nodejs}/bin/node"; | ||
jq = "${jq.nativeDrv or jq}/bin/jq"; | ||
}; | ||
} ./npm-install-hook.sh; | ||
} |
37 changes: 37 additions & 0 deletions
37
pkgs/build-support/node/build-npm-package/hooks/npm-build-hook.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# shellcheck shell=bash | ||
|
||
npmBuildHook() { | ||
echo "Executing npmBuildHook" | ||
|
||
runHook preBuild | ||
|
||
if [ -z "${npmBuildScript-}" ]; then | ||
echo | ||
echo "ERROR: no build script was specified" | ||
echo 'Hint: set `npmBuildScript`, override `buildPhase`, or set `dontNpmBuild = true`.' | ||
echo | ||
|
||
exit 1 | ||
fi | ||
|
||
if ! npm run "$npmBuildScript" $npmBuildFlags "${npmBuildFlagsArray[@]}" $npmFlags "${npmFlagsArray[@]}"; then | ||
echo | ||
echo 'ERROR: `npm build` failed' | ||
echo | ||
echo "Here are a few things you can try, depending on the error:" | ||
echo "1. Make sure your build script ($npmBuildScript) exists" | ||
echo '2. If the error being thrown is something similar to "error:0308010C:digital envelope routines::unsupported", add `NODE_OPTIONS = "--openssl-legacy-provider"` to your derivation' | ||
echo " See https://github.com/webpack/webpack/issues/14532 for more information." | ||
echo | ||
|
||
exit 1 | ||
fi | ||
|
||
runHook postBuild | ||
|
||
echo "Finished npmBuildHook" | ||
} | ||
|
||
if [ -z "${dontNpmBuild-}" ] && [ -z "${buildPhase-}" ]; then | ||
buildPhase=npmBuildHook | ||
fi |
102 changes: 102 additions & 0 deletions
102
pkgs/build-support/node/build-npm-package/hooks/npm-config-hook.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
# shellcheck shell=bash | ||
|
||
npmConfigHook() { | ||
echo "Executing npmConfigHook" | ||
|
||
echo "Configuring npm" | ||
|
||
export HOME=$TMPDIR | ||
export npm_config_nodedir="@nodeSrc@" | ||
|
||
local -r cacheLockfile="$npmDeps/package-lock.json" | ||
local -r srcLockfile="$PWD/package-lock.json" | ||
|
||
echo "Validating consistency between $srcLockfile and $cacheLockfile" | ||
|
||
if ! @diff@ "$srcLockfile" "$cacheLockfile"; then | ||
# If the diff failed, first double-check that the file exists, so we can | ||
# give a friendlier error msg. | ||
if ! [ -e "$srcLockfile" ]; then | ||
echo | ||
echo "ERROR: Missing package-lock.json from src. Expected to find it at: $srcLockfile" | ||
echo "Hint: You can use the patches attribute to add a package-lock.json manually to the build." | ||
echo | ||
|
||
exit 1 | ||
fi | ||
|
||
if ! [ -e "$cacheLockfile" ]; then | ||
echo | ||
echo "ERROR: Missing lockfile from cache. Expected to find it at: $cacheLockfile" | ||
echo | ||
|
||
exit 1 | ||
fi | ||
|
||
echo | ||
echo "ERROR: npmDepsHash is out of date" | ||
echo | ||
echo "The package-lock.json in src is not the same as the in $npmDeps." | ||
echo | ||
echo "To fix the issue:" | ||
echo '1. Use `lib.fakeHash` as the npmDepsHash value' | ||
echo "2. Build the derivation and wait for it to fail with a hash mismatch" | ||
echo "3. Copy the 'got: sha256-' value back into the npmDepsHash field" | ||
echo | ||
|
||
exit 1 | ||
fi | ||
|
||
local cachePath | ||
|
||
if [ -z "${makeCacheWritable-}" ]; then | ||
cachePath=$npmDeps | ||
else | ||
echo "Making cache writable" | ||
cp -r "$npmDeps" "$TMPDIR/cache" | ||
chmod -R 700 "$TMPDIR/cache" | ||
cachePath=$TMPDIR/cache | ||
fi | ||
|
||
npm config set cache "$cachePath" | ||
npm config set offline true | ||
npm config set progress false | ||
|
||
echo "Installing dependencies" | ||
|
||
if ! npm ci --ignore-scripts $npmInstallFlags "${npmInstallFlagsArray[@]}" $npmFlags "${npmFlagsArray[@]}"; then | ||
echo | ||
echo "ERROR: npm failed to install dependencies" | ||
echo | ||
echo "Here are a few things you can try, depending on the error:" | ||
echo '1. Set `makeCacheWritable = true`' | ||
echo " Note that this won't help if npm is complaining about not being able to write to the logs directory -- look above that for the actual error." | ||
echo '2. Set `npmInstallFlags = [ "--legacy-peer-deps" ]`' | ||
echo | ||
|
||
exit 1 | ||
fi | ||
|
||
patchShebangs node_modules | ||
|
||
local -r lockfileVersion="$(@jq@ .lockfileVersion package-lock.json)" | ||
|
||
if (( lockfileVersion < 2 )); then | ||
# This is required because npm consults a hidden lockfile in node_modules to figure out | ||
# what to create bin links for. When using an old lockfile offline, this hidden lockfile | ||
# contains insufficent data, making npm silently fail to create links. The hidden lockfile | ||
# is bypassed when any file in node_modules is newer than it. Thus, we create a file when | ||
# using an old lockfile, so bin links work as expected without having to downgrade Node or npm. | ||
touch node_modules/.meow | ||
fi | ||
|
||
npm rebuild "${npmRebuildFlags[@]}" "${npmFlags[@]}" | ||
|
||
if (( lockfileVersion < 2 )); then | ||
rm node_modules/.meow | ||
fi | ||
|
||
echo "Finished npmConfigHook" | ||
} | ||
|
||
postPatchHooks+=(npmConfigHook) |
43 changes: 43 additions & 0 deletions
43
pkgs/build-support/node/build-npm-package/hooks/npm-install-hook.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# shellcheck shell=bash | ||
|
||
npmInstallHook() { | ||
echo "Executing npmInstallHook" | ||
|
||
runHook preInstall | ||
|
||
# `npm pack` writes to cache | ||
npm config delete cache | ||
|
||
local -r packageOut="$out/lib/node_modules/$(@jq@ --raw-output '.name' package.json)" | ||
|
||
while IFS= read -r file; do | ||
local dest="$packageOut/$(dirname "$file")" | ||
mkdir -p "$dest" | ||
cp "$file" "$dest" | ||
done < <(@jq@ --raw-output '.[0].files | map(.path) | join("\n")' <<< "$(npm pack --json --dry-run $npmPackFlags "${npmPackFlagsArray[@]}" $npmFlags "${npmFlagsArray[@]}")") | ||
|
||
while IFS=" " read -ra bin; do | ||
mkdir -p "$out/bin" | ||
makeWrapper @hostNode@ "$out/bin/${bin[0]}" --add-flags "$packageOut/${bin[1]}" | ||
done < <(@jq@ --raw-output '(.bin | type) as $typ | if $typ == "string" then | ||
.name + " " + .bin | ||
elif $typ == "object" then .bin | to_entries | map(.key + " " + .value) | join("\n") | ||
else "invalid type " + $typ | halt_error end' package.json) | ||
|
||
local -r nodeModulesPath="$packageOut/node_modules" | ||
|
||
if [ ! -d "$nodeModulesPath" ]; then | ||
npm prune --omit dev | ||
find node_modules -maxdepth 1 -type d -empty -delete | ||
|
||
cp -r node_modules "$nodeModulesPath" | ||
fi | ||
|
||
runHook postInstall | ||
|
||
echo "Finished npmInstallHook" | ||
} | ||
|
||
if [ -z "${dontNpmInstall-}" ] && [ -z "${installPhase-}" ]; then | ||
installPhase=npmInstallHook | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/target |
Oops, something went wrong.