|
18 | 18 | versionsData = builtins.fromJSON (builtins.readFile ./versions.json); |
19 | 19 | versionMap = versionsData.versions; |
20 | 20 |
|
| 21 | + # The default version shown as `packages.<system>.default`. |
| 22 | + # Set "default" in versions.json to override; falls back to "22.22". |
| 23 | + defaultVersion = versionsData.default or "22.22"; |
| 24 | + |
| 25 | + # Converts "22.22" → "22_22" for use as Nix attribute names. |
| 26 | + sanitizeVersion = builtins.replaceStrings [ "." ] [ "_" ]; |
| 27 | + |
21 | 28 | systems = [ |
22 | 29 | "x86_64-linux" |
23 | 30 | "aarch64-linux" |
|
43 | 50 |
|
44 | 51 | # NOTE: This uses an impure fetchTarball, which is often discouraged |
45 | 52 | # in top-level packages, but is sometimes accepted for version pins. |
| 53 | + # |
| 54 | + # allowInsecurePredicate is scoped to Node.js and OpenSSL packages only. |
| 55 | + # Old Node.js versions (14.x, 16.x) bundle EOL OpenSSL and are flagged |
| 56 | + # insecure by nixpkgs; we need to allow them intentionally here. |
46 | 57 | getNixpkgs = |
47 | 58 | { system, version }: |
48 | | - if hasVersion { inherit version; } then |
49 | | - let |
50 | | - info = versionMap.${version}; |
51 | | - in |
52 | | - import |
53 | | - (builtins.fetchTarball { |
54 | | - url = "https://github.com/NixOS/nixpkgs/archive/${info.rev}.tar.gz"; |
55 | | - sha256 = info.sha256; |
56 | | - }) |
57 | | - { |
58 | | - inherit system; |
59 | | - config.allowUnfree = true; |
60 | | - config.allowInsecurePredicate = (_: true); |
61 | | - } |
62 | | - else |
63 | | - throw "Node.js version ${version} not found in versionMap"; |
| 59 | + let |
| 60 | + info = getVersionInfo version; |
| 61 | + in |
| 62 | + import |
| 63 | + (builtins.fetchTarball { |
| 64 | + url = "https://github.com/NixOS/nixpkgs/archive/${info.rev}.tar.gz"; |
| 65 | + sha256 = info.sha256; |
| 66 | + }) |
| 67 | + { |
| 68 | + inherit system; |
| 69 | + config.allowInsecurePredicate = |
| 70 | + pkg: |
| 71 | + builtins.match "nodejs.*" pkg.pname != null |
| 72 | + || builtins.match "openssl.*" pkg.pname != null; |
| 73 | + }; |
64 | 74 | }; |
65 | 75 |
|
66 | 76 | packagesForSystem = |
|
83 | 93 |
|
84 | 94 | aliases = nixpkgs.lib.mapAttrs' ( |
85 | 95 | version: pkg: |
86 | | - nixpkgs.lib.nameValuePair ("nodejs_" + (builtins.replaceStrings [ "." ] [ "_" ] version)) pkg |
| 96 | + nixpkgs.lib.nameValuePair ("nodejs_" + sanitizeVersion version) pkg |
87 | 97 | ) basePackages; |
88 | 98 |
|
89 | 99 | # Create yarn packages bundled with the specific node version. |
90 | | - # Uses the version-pinned nixpkgs to ensure yarn/node compatibility |
| 100 | + # Uses the version-pinned nixpkgs to ensure yarn/node compatibility. |
91 | 101 | # Falls back to latest nixpkgs if yarn is absent from the pinned rev. |
92 | 102 | # yarn.override is a callable attrset (same structure as pnpm); __functionArgs |
93 | 103 | # is checked before calling to guard against future packaging changes. |
|
102 | 112 | && yarnOverride ? __functionArgs |
103 | 113 | && builtins.hasAttr "nodejs" yarnOverride.__functionArgs; |
104 | 114 | in |
105 | | - nixpkgs.lib.nameValuePair ("yarn_" + (builtins.replaceStrings [ "." ] [ "_" ] version)) ( |
| 115 | + nixpkgs.lib.nameValuePair ("yarn_" + sanitizeVersion version) ( |
106 | 116 | pkgs.symlinkJoin { |
107 | 117 | name = "yarn-" + version; |
108 | 118 | paths = [ |
|
119 | 129 | # |
120 | 130 | # Older nixpkgs keep pnpm under nodePackages.pnpm; newer ones promote it to |
121 | 131 | # pkgs.pnpm with a callable-attrset override that accepts a nodejs argument. |
122 | | - # When that override is available we thread |
123 | | - # our exact Node derivation through it; otherwise we use pnpm as-is. |
| 132 | + # When that override is available we thread our exact Node derivation through |
| 133 | + # it; otherwise we use pnpm as-is. |
124 | 134 | # |
125 | 135 | # Falls back to latest nixpkgs pnpm only when the pinned rev has no pnpm at |
126 | | - # all (rare, but guards against evaluation errors). |
| 136 | + # all (rare, but guards against evaluation errors). The fallback also applies |
| 137 | + # the same __functionArgs guard for consistency. |
127 | 138 | pnpmPackages = nixpkgs.lib.mapAttrs' ( |
128 | 139 | version: pkg: |
129 | 140 | let |
|
143 | 154 |
|
144 | 155 | pnpmPkg = |
145 | 156 | if builtins.isNull pinnedPnpm then |
146 | | - pkgs.pnpm.override { nodejs = pkg; } |
| 157 | + # Pinned rev has no pnpm at all; fall back to unstable nixpkgs. |
| 158 | + # Apply the same __functionArgs guard — pkgs is always modern but |
| 159 | + # defensive coding avoids future breakage. |
| 160 | + let |
| 161 | + fallbackOverride = pkgs.pnpm.override or null; |
| 162 | + canOverrideFallback = |
| 163 | + builtins.isAttrs fallbackOverride |
| 164 | + && fallbackOverride ? __functionArgs |
| 165 | + && builtins.hasAttr "nodejs" fallbackOverride.__functionArgs; |
| 166 | + in |
| 167 | + if canOverrideFallback then fallbackOverride { nodejs = pkg; } else pkgs.pnpm |
147 | 168 | else if canOverrideNodejs then |
148 | 169 | pnpmOverride { nodejs = pkg; } |
149 | 170 | else |
150 | 171 | pinnedPnpm; |
151 | 172 | in |
152 | | - nixpkgs.lib.nameValuePair ("pnpm_" + (builtins.replaceStrings [ "." ] [ "_" ] version)) ( |
| 173 | + nixpkgs.lib.nameValuePair ("pnpm_" + sanitizeVersion version) ( |
153 | 174 | pkgs.symlinkJoin { |
154 | 175 | name = "pnpm-" + version; |
| 176 | + # pkg first: symlinkJoin uses lndir which skips existing symlinks, |
| 177 | + # so the first path wins on conflict. pkg must win for node/npm/npx. |
155 | 178 | paths = [ |
156 | 179 | pkg |
157 | 180 | pnpmPkg |
|
168 | 191 | let |
169 | 192 | allPkgs = packagesForSystem system; |
170 | 193 | in |
171 | | - allPkgs // { default = allPkgs."22.22"; } |
| 194 | + allPkgs |
| 195 | + // { |
| 196 | + default = |
| 197 | + allPkgs.${defaultVersion} |
| 198 | + or (throw "Default Node.js version '${defaultVersion}' not found in versions.json"); |
| 199 | + } |
172 | 200 | ); |
173 | 201 |
|
174 | 202 | overlays.default = |
|
0 commit comments