{ lib, stdenv, bun, nodejs, writableTmpDirAsHomeHook, }: let workspacePreparePatched = [ "apps/server/package.json" "apps/web/package.json" "packages/client-runtime/package.json" "packages/contracts/package.json" "packages/effect-acp/package.json" "packages/effect-codex-app-server/package.json" "packages/shared/package.json" ]; renderBunFilters = filters: lib.concatMapStringsSep "\n" (filter: " --filter ${filter} \\") filters; in { inherit workspacePreparePatched; # `bun.lock` pins dependency resolution, but Bun's materialized install tree is # not stable enough to hash directly across machines. Normalize Bun-managed # layout before the fixed-output copy, and keep native rebuilds outside the FOD. mkNodeModules = { pname, version, src, outputHash, filters, extraNativeBuildInputs ? [], impureEnvVars ? [], extraEnv ? "", }: stdenv.mkDerivation { pname = "${pname}-node-modules"; inherit version src impureEnvVars; nativeBuildInputs = [ bun nodejs writableTmpDirAsHomeHook ] ++ extraNativeBuildInputs; dontConfigure = true; dontFixup = true; postPatch = '' for packageJson in ${lib.concatStringsSep " " workspacePreparePatched}; do substituteInPlace "$packageJson" \ --replace-fail '"prepare": "effect-language-service patch"' '"prepare": "true"' done ''; buildPhase = '' runHook preBuild export HOME="$TMPDIR" export BUN_INSTALL_CACHE_DIR="$(mktemp -d)" ${extraEnv} bun install \ --frozen-lockfile \ --ignore-scripts \ --backend=copyfile \ --linker=hoisted \ --no-progress \ ${renderBunFilters filters} bun --bun ${./scripts/canonicalize-node-modules.ts} bun --bun ${./scripts/normalize-bun-binaries.ts} runHook postBuild ''; installPhase = '' runHook preInstall mkdir -p "$out" cp -RP ./node_modules/. "$out/" find "$out" -type d -exec chmod u+rwx,go+rx {} + find "$out" -type f -exec chmod u+rw,go+r {} + find "$out" -type f \( -path "$out/.bin/*" -o -path '*/node_modules/.bin/*' \) -exec chmod u+rwx,go+rx {} + find "$out" -exec touch -h -d '@1' {} + runHook postInstall ''; inherit outputHash; outputHashAlgo = "sha256"; outputHashMode = "recursive"; }; mkNodePtyConfigurePhase = { nodeModules, chmodBins ? false, }: '' runHook preConfigure mkdir -p ./node_modules cp -R ${nodeModules}/. ./node_modules/ chmod -R u+rwX node_modules if [ ${if chmodBins then "true" else "false"} = true ] && [ -d node_modules/.bin ]; then chmod -R u+x node_modules/.bin fi patchShebangs node_modules cd node_modules/node-pty node-gyp rebuild node scripts/post-install.js cd "$NIX_BUILD_TOP/$sourceRoot" runHook postConfigure ''; }