{prev}: let # n8n >= 2.32 replaced the sheetjs-CDN `xlsx@0.20.2` tarball (which lacked an # integrity checksum and had to be patched into pnpm-lock.yaml) with the # regular npm package `@e965/xlsx@0.20.3`, which already carries an integrity # field. The old lockfile-integrity workaround is therefore obsolete and has # been removed. # # n8n >= 2.37.0 demands pnpm >= 11.22.0 via `engines.pnpm`, but the pinned # nixpkgs only ships pnpm_10 (10.34.5) and pnpm_11 (11.17.0) — both too old. # pnpm enforces that gate for ITSELF regardless of `engine-strict`, so both # fetchPnpmDeps and the main build die with ERR_PNPM_UNSUPPORTED_ENGINE # before any hash mismatch is even reached. Additionally n8n's lockfile, # while still declaring lockfileVersion '9.0', now serialises # patchedDependencies as plain `name@version: hash` scalars (no `path:` # mapping), which pnpm 10 cannot parse (ERR_PNPM_LOCKFILE_CONFIG_MISMATCH). # We therefore build with pnpm_11 + fetcherVersion 4 and relax the engine # gate in package.json. Drop the sed once nixpkgs ships pnpm >= 11.22 and # this overlay's nixpkgs pin has caught up. relaxPnpmEngine = '' sed -i -E 's/"pnpm": *"[^"]*"/"pnpm": "*"/' package.json ''; in prev.n8n.overrideAttrs (finalAttrs: previousAttrs: { version = "2.39.6"; src = prev.fetchFromGitHub { owner = "n8n-io"; repo = "n8n"; tag = "n8n@${finalAttrs.version}"; hash = "sha256-fmo0xL6IF6J+D5ZamkoBXyZ4Q8s3l5MeBWaXc39OsTU="; }; pnpmDeps = prev.fetchPnpmDeps { inherit (finalAttrs) pname version src; pnpm = prev.pnpm_11; fetcherVersion = 4; postPatch = relaxPnpmEngine; hash = "sha256-yL95w+Jd5I5R6r/qNihvAJ4MX2LMyS9ICZzJnLxHR4s="; }; postPatch = (previousAttrs.postPatch or "") + relaxPnpmEngine; # Swap pnpm_10 -> pnpm_11 from the inherited nativeBuildInputs: upstream # n8n calls pnpm directly during the build (install/build/prune) and pnpm 10 # cannot parse the pnpm-11 lockfile. The top-level pnpmConfigHook stays as # is — it discovers the fetcher version from pnpmDeps' .fetcher-version. nativeBuildInputs = builtins.map (x: if (x.outPath or null) == prev.pnpm_10.outPath then prev.pnpm_11 else x) previousAttrs.nativeBuildInputs; preBuild = (previousAttrs.preBuild or "") + '' if [ ! -e node_modules/sass-embedded ] && [ -e node_modules/.pnpm/node_modules/sass-embedded ]; then ln -s .pnpm/node_modules/sass-embedded node_modules/sass-embedded fi if [ ! -e node_modules/sqlite3 ] && [ -e node_modules/.pnpm/node_modules/sqlite3 ]; then ln -s .pnpm/node_modules/sqlite3 node_modules/sqlite3 fi ''; # Self-contained update script (./update.sh) — fetches latest stable # release from n8n-io/n8n, recomputes both src and pnpmDeps hashes. # The CI workflow in .gitea/workflows/nix-update.yml discovers and runs it. passthru = (previousAttrs.passthru or {}) // {updateScript = ./update.sh;}; meta = previousAttrs.meta // { changelog = "https://github.com/n8n-io/n8n/releases/tag/n8n@${finalAttrs.version}"; }; })