deno-with-packages/lib/lockfile-to-npm-deps.nix

69 lines
1.8 KiB
Nix

{ self }:
{ pkgs, lockfile }:
let
registry = self.denoNpmRegistryHostname;
# Extract npm dependencies from a single lockfile
extractNpmDeps = lockfile:
let
lockJSON = builtins.fromJSON (builtins.readFile lockfile);
in
lockJSON.npm or {};
npmDeps = extractNpmDeps lockfile;
# Create tarball derivation for a package
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://${registry}/${name}/-/${tarballName}-${version}.tgz";
hash = integrity;
};
# Create derivation for a single npm package
mkNpmDep = key: value:
let
match = builtins.match "(@?[^@]+)@([^_]+).*" key;
name = builtins.elemAt match 0;
version = builtins.elemAt match 1;
in
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/npm/${registry}/${name}/${version}"
mkdir -p $OUT_PATH
tar -xzf $src -C $OUT_PATH --strip-components=1
SUBSET_FILTER='to_entries | map(select(.key == "version" or .key == "bin" or .key == "dependencies" or .key == "peerDependencies")) | from_entries'
PACKAGE_SUBSET=$(${pkgs.jq}/bin/jq "$SUBSET_FILTER" $OUT_PATH/package.json)
cat > $OUT_PATH/../registry.json <<EOF
{
"name": "${name}",
"dist-tags": {},
"versions": {
"${version}": $PACKAGE_SUBSET
}
}
EOF
runHook postInstall
'';
};
in
pkgs.lib.mapAttrsToList mkNpmDep npmDeps