1{
2 lib,
3 stdenvNoCC,
4 callPackage,
5 jq,
6 moreutils,
7 cacert,
8 makeSetupHook,
9 pnpm,
10 yq,
11}:
12
13let
14 pnpm' = pnpm;
15
16 supportedFetcherVersions = [
17 1 # First version. Here to preserve backwards compatibility
18 2 # Ensure consistent permissions. See https://github.com/NixOS/nixpkgs/pull/422975
19 ];
20in
21{
22 fetchDeps = lib.makeOverridable (
23 {
24 hash ? "",
25 pname,
26 pnpm ? pnpm',
27 pnpmWorkspaces ? [ ],
28 prePnpmInstall ? "",
29 pnpmInstallFlags ? [ ],
30 fetcherVersion ? null,
31 ...
32 }@args:
33 let
34 args' = builtins.removeAttrs args [
35 "hash"
36 "pname"
37 ];
38 hash' =
39 if hash != "" then
40 { outputHash = hash; }
41 else
42 {
43 outputHash = "";
44 outputHashAlgo = "sha256";
45 };
46
47 filterFlags = lib.map (package: "--filter=${package}") pnpmWorkspaces;
48 in
49 # pnpmWorkspace was deprecated, so throw if it's used.
50 assert (lib.throwIf (args ? pnpmWorkspace)
51 "pnpm.fetchDeps: `pnpmWorkspace` is no longer supported, please migrate to `pnpmWorkspaces`."
52 ) true;
53
54 assert (lib.throwIf (fetcherVersion == null)
55 "pnpm.fetchDeps: `fetcherVersion` is not set, see https://nixos.org/manual/nixpkgs/stable/#javascript-pnpm-fetcherVersion."
56 ) true;
57
58 assert (lib.throwIf (!(builtins.elem fetcherVersion supportedFetcherVersions))
59 "pnpm.fetchDeps `fetcherVersion` is not set to a supported value (${lib.concatStringsSep ", " (builtins.map toString supportedFetcherVersions)}), see https://nixos.org/manual/nixpkgs/stable/#javascript-pnpm-fetcherVersion."
60 ) true;
61
62 stdenvNoCC.mkDerivation (
63 finalAttrs:
64 (
65 args'
66 // {
67 name = "${pname}-pnpm-deps";
68
69 nativeBuildInputs = [
70 cacert
71 jq
72 moreutils
73 args.pnpm or pnpm'
74 yq
75 ];
76
77 impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [ "NIX_NPM_REGISTRY" ];
78
79 installPhase = ''
80 runHook preInstall
81
82 lockfileVersion="$(yq -r .lockfileVersion pnpm-lock.yaml)"
83 if [[ ''${lockfileVersion:0:1} -gt ${lib.versions.major pnpm.version} ]]; then
84 echo "ERROR: lockfileVersion $lockfileVersion in pnpm-lock.yaml is too new for the provided pnpm version ${lib.versions.major pnpm.version}!"
85 exit 1
86 fi
87
88 export HOME=$(mktemp -d)
89
90 # If the packageManager field in package.json is set to a different pnpm version than what is in nixpkgs,
91 # any pnpm command would fail in that directory, the following disables this
92 pushd ..
93 pnpm config set manage-package-manager-versions false
94 popd
95
96 pnpm config set store-dir $out
97 # Some packages produce platform dependent outputs. We do not want to cache those in the global store
98 pnpm config set side-effects-cache false
99 # As we pin pnpm versions, we don't really care about updates
100 pnpm config set update-notifier false
101 # Run any additional pnpm configuration commands that users provide.
102 ${prePnpmInstall}
103 # pnpm is going to warn us about using --force
104 # --force allows us to fetch all dependencies including ones that aren't meant for our host platform
105 pnpm install \
106 --force \
107 --ignore-scripts \
108 ${lib.escapeShellArgs filterFlags} \
109 ${lib.escapeShellArgs pnpmInstallFlags} \
110 --registry="$NIX_NPM_REGISTRY" \
111 --frozen-lockfile
112
113 # Store newer fetcherVersion in case pnpm.configHook also needs it
114 if [[ ${toString fetcherVersion} -gt 1 ]]; then
115 echo ${toString fetcherVersion} > $out/.fetcher-version
116 fi
117
118 runHook postInstall
119 '';
120
121 fixupPhase = ''
122 runHook preFixup
123
124 # Remove timestamp and sort the json files
125 rm -rf $out/{v3,v10}/tmp
126 for f in $(find $out -name "*.json"); do
127 jq --sort-keys "del(.. | .checkedAt?)" $f | sponge $f
128 done
129
130 # Ensure consistent permissions
131 # NOTE: For reasons not yet fully understood, pnpm might create files with
132 # inconsistent permissions, for example inside the ubuntu-24.04
133 # github actions runner.
134 # To ensure stable derivations, we need to set permissions
135 # consistently, namely:
136 # * All files with `-exec` suffix have 555.
137 # * All other files have 444.
138 # * All folders have 555.
139 # See https://github.com/NixOS/nixpkgs/pull/350063
140 # See https://github.com/NixOS/nixpkgs/issues/422889
141 if [[ ${toString fetcherVersion} -ge 2 ]]; then
142 find $out -type f -name "*-exec" -print0 | xargs -0 chmod 555
143 find $out -type f -not -name "*-exec" -print0 | xargs -0 chmod 444
144 find $out -type d -print0 | xargs -0 chmod 555
145 fi
146
147 runHook postFixup
148 '';
149
150 passthru = {
151 inherit fetcherVersion;
152 serve = callPackage ./serve.nix {
153 pnpm = args.pnpm or pnpm';
154 pnpmDeps = finalAttrs.finalPackage;
155 };
156 };
157
158 dontConfigure = true;
159 dontBuild = true;
160 outputHashMode = "recursive";
161 }
162 // hash'
163 )
164 )
165 );
166
167 configHook = makeSetupHook {
168 name = "pnpm-config-hook";
169 propagatedBuildInputs = [ pnpm ];
170 substitutions = {
171 npmArch = stdenvNoCC.targetPlatform.node.arch;
172 npmPlatform = stdenvNoCC.targetPlatform.node.platform;
173 };
174 } ./pnpm-config-hook.sh;
175}