{ pkgs }: rec { denoLockfileToNpmDeps = { lockfile, registryHostname }: let extractNpmDeps = lockfile: let lockJSON = builtins.fromJSON (builtins.readFile lockfile); in lockJSON.npm or { }; npmDeps = extractNpmDeps lockfile; mkTarballDrv = { name, version, integrity, }: let tarballName = if builtins.substring 0 1 name == "@" then builtins.baseNameOf name # "@types/node" -> "node" else name; in pkgs.fetchurl { url = "https://${registryHostname}/${name}/-/${tarballName}-${version}.tgz"; hash = integrity; }; mkNpmDep = key: value: let match = builtins.match "(@?[^@]+)@([^_]+).*" key; name = builtins.elemAt match 0; version = builtins.elemAt match 1; cachePath = "npm/${registryHostname}/${name}"; in { drv = pkgs.stdenv.mkDerivation { pname = "deno-npm-${builtins.replaceStrings [ "@" "/" ] [ "" "-" ] name}"; version = version; src = mkTarballDrv { inherit name version; inherit (value) integrity; }; installPhase = '' runHook preInstall export OUT_PATH="$out/${cachePath}/${version}" mkdir -p $OUT_PATH tar -xzf $src -C $OUT_PATH --strip-components=1 runHook postInstall ''; }; inherit name cachePath; }; in pkgs.lib.mapAttrsToList mkNpmDep npmDeps; denoSharedCache = { lockfiles, registryHostname }: let allNpmDeps = builtins.concatMap ( lockfile: denoLockfileToNpmDeps { inherit lockfile registryHostname; } ) lockfiles; sharedCacheBase = pkgs.symlinkJoin { name = "deno-shared-cache-base"; paths = map (d: d.drv) allNpmDeps; }; in pkgs.runCommand "deno-shared-cache" {} '' runHook preInstall mkdir -p $out chmod -R +w $out cp -rs ${sharedCacheBase}/* $out while IFS='|' read -r dep name; do chmod +w $out/$dep cat > $out/$dep/registry.json < $out/$dep/registry.json.tmp mv $out/$dep/registry.json.tmp $out/$dep/registry.json done < <(find $out/$dep -mindepth 1 -maxdepth 1 -type d | xargs -n1 basename) done < <(echo "${builtins.concatStringsSep "\n" (map (d: "${d.cachePath}|${d.name}") allNpmDeps)}" | sort -u) runHook postInstall ''; denoWithCache = { baseDeno, sharedCache, dir }: pkgs.writeShellScriptBin "deno" '' set -euo pipefail # Use configured dir, with support for FLAKE_ROOT variable expansion CACHE_DIR="${dir}" if [ ! -d "$CACHE_DIR" ] || [ ! "$(ls -A "$CACHE_DIR" 2>/dev/null)" ]; then echo "Setting up Deno cache at: $CACHE_DIR" >&2 mkdir -p "$CACHE_DIR" if [ -d "${sharedCache}" ]; then echo "Copying shared cache..." >&2 cp -rL "${sharedCache}"/* "$CACHE_DIR"/ 2>/dev/null || true chmod -R u+w "$CACHE_DIR" 2>/dev/null || true fi fi export DENO_DIR="$CACHE_DIR" exec "${baseDeno}/bin/deno" "$@" ''; }