nixos/packages/mkPnpmPackage.nix
2024-08-01 00:25:23 +08:00

87 lines
3.6 KiB
Nix

{ lib, remarshal, fetchurl, runCommand, nodejs, stdenv, pkg-config, writeText }:
{
src,
lockFile ? "${src}/pnpm-lock.yaml",
packageFile ? "${src}/package.json",
pname ? (builtins.fromJSON (builtins.readFile packageFile)).name,
version ? (builtins.fromJSON (builtins.readFile packageFile)).version or null,
extraIntegritySha256 ? {},
registry ? "https://registry.npmjs.org",
extraNativeBuildInputs ? [],
buildScript ? "build",
extraAttrs ? {},
}:
let
originalLock = builtins.fromJSON
(builtins.readFile (runCommand "toJSON" { } "${remarshal}/bin/yaml2json ${lockFile} $out"));
patchedLock = originalLock
// {
packages = lib.mapAttrs
(name: value:
if (value.resolution ? integrity) == (value.resolution ? tarball)
then throw "could not determine source ${name}"
else if value.resolution ? integrity then
# name maybe /@vue/compiler-core@3.4.18 or @vue/compiler-core@3.4.18
# or /@storybook/core-server@8.0.0-beta.6(react-dom@18.2.0)(react@18.2.0)
let nameAtVersion = builtins.head (lib.splitString "(" name);
in let
version = lib.last (lib.splitString "@" nameAtVersion);
name = lib.last (lib.init (lib.splitString "@" nameAtVersion));
baseName = lib.last (lib.splitString "/" name);
url = "${registry}/${if name == baseName then "" else "@"}${name}/-/${baseName}-${version}.tgz";
tarball = fetchurl { inherit url; sha512 = value.resolution.integrity; };
in value // { resolution.tarball = "file:${tarball}"; }
else # if value.resolution ? tarball then
if lib.hasPrefix "https://codeload.github.com" value.resolution.tarball then
let
match = lib.strings.match
"https://codeload.github.com/([^/]+)/([^/]+)/tar\\.gz/([a-f0-9]+)" value.resolution.tarball;
repo = fetchGit
{
url = "https://github.com/${builtins.elemAt match 0}/${builtins.elemAt match 1}";
rev = builtins.elemAt match 2;
shallow = true;
};
tarball = runCommand "${builtins.elemAt match 1}.tgz" {} "tar -czf $out -C ${repo} .";
in value // { resolution.tarball = "file:${tarball}"; }
else
let tarball = fetchurl rec
{ url = value.resolution.tarball; sha256 = extraIntegritySha256.${url}; };
in value // { resolution.tarball = "file:${tarball}"; }
)
originalLock.packages;
};
patchedLockFile = writeText "pnpm-lock.yaml" (builtins.toJSON patchedLock);
in stdenv.mkDerivation
({
inherit src pname version;
nativeBuildInputs = [ nodejs nodejs.pkgs.pnpm pkg-config ] ++ extraNativeBuildInputs;
configurePhase =
''
runHook preConfigure
export HOME=$NIX_BUILD_TOP # Some packages need a writable HOME
export npm_config_nodedir=${nodejs}
pnpm config set reporter append-only
pnpm config set package-manager-strict false
cp -f ${patchedLockFile} pnpm-lock.yaml
runHook postConfigure
'';
buildPhase =
''
runHook preBuild
pnpm install --frozen-lockfile --offline
pnpm run ${buildScript}
runHook postBuild
'';
installPhase =
''
runHook preInstall
mkdir -p $out
mv * .* $out
runHook postInstall
'';
} // extraAttrs)