diff --git a/doc/languages-frameworks/javascript.section.md b/doc/languages-frameworks/javascript.section.md index f85a416fee86..3af4d1d86099 100644 --- a/doc/languages-frameworks/javascript.section.md +++ b/doc/languages-frameworks/javascript.section.md @@ -327,16 +327,17 @@ See `node2nix` [docs](https://github.com/svanderburg/node2nix) for more info. ### pnpm {#javascript-pnpm} -Pnpm is available as the top-level package `pnpm`. Additionally, there are variants pinned to certain major versions, like `pnpm_8` and `pnpm_9`, which support different sets of lock file versions. +pnpm is available as the top-level package `pnpm`. Additionally, there are variants pinned to certain major versions, like `pnpm_8`, `pnpm_9` and `pnpm_10`, which support different sets of lock file versions. -When packaging an application that includes a `pnpm-lock.yaml`, you need to fetch the pnpm store for that project using a fixed-output-derivation. The functions `pnpm_8.fetchDeps` and `pnpm_9.fetchDeps` can create this pnpm store derivation. In conjunction, the setup hooks `pnpm_8.configHook` and `pnpm_9.configHook` will prepare the build environment to install the pre-fetched dependencies store. Here is an example for a package that contains `package.json` and a `pnpm-lock.yaml` files using the above `pnpm_` attributes: +When packaging an application that includes a `pnpm-lock.yaml`, you need to fetch the pnpm store for that project using a fixed-output-derivation. The function `fetchPnpmDeps` can create this pnpm store derivation. In conjunction, the setup hook `pnpmConfigHook` will prepare the build environment to install the pre-fetched dependencies store. Here is an example for a package that contains `package.json` and a `pnpm-lock.yaml` files using the fetcher and setup hook above: ```nix { - stdenv, + fetchPnpmDeps, nodejs, - # This is pinned as { pnpm = pnpm_9; } pnpm, + pnpmConfigHook, + stdenv, }: stdenv.mkDerivation (finalAttrs: { @@ -348,11 +349,12 @@ stdenv.mkDerivation (finalAttrs: { }; nativeBuildInputs = [ - nodejs - pnpm.configHook + nodejs # in case scripts are run outside of a pnpm call + pnpmConfigHook + pnpm # At least required by pnpmConfigHook, if not other (custom) phases ]; - pnpmDeps = pnpm.fetchDeps { + pnpmDeps = fetchPnpmDeps { inherit (finalAttrs) pname version src; fetcherVersion = 3; hash = "..."; @@ -360,33 +362,68 @@ stdenv.mkDerivation (finalAttrs: { }) ``` -NOTE: It is highly recommended to use a pinned version of pnpm (i.e., `pnpm_8` or `pnpm_9`), to increase future reproducibility. It might also be required to use an older version if the package needs support for a certain lock file version. +It is highly recommended to use a pinned version of pnpm (i.e., `pnpm_9` or `pnpm_10`), to increase future reproducibility. It might also be required to use an older version if the package needs support for a certain lock file version. To do so, you can pass the `pnpm` argument to `fetchPnpmDeps` and override the `pnpm` arg in `pnpmConfigHook`. Here are the changes in the example above to use a pinned pnpm version: + + + +```diff + { + fetchPnpmDeps, + nodejs, +- pnpm, ++ pnpm_10, + pnpmConfigHook, + stdenv, + }: ++let ++ # Optionally override pnpm to use a custom nodejs version ++ # Make sure that the same nodejs version is referenced in nativeBuildInputs ++ # pnpm = pnpm_10.override { nodejs = nodejs_20; }; ++in + stdenv.mkDerivation (finalAttrs: { + pname = "foo"; + version = "0-unstable-1980-01-01"; + + src = { + #... + }; + + nativeBuildInputs = [ + nodejs # in case scripts are run outside of a pnpm call + pnpmConfigHook +- pnpm # At least required by pnpmConfigHook, if not other (custom) phases ++ pnpm_10 # At least required by pnpmConfigHook, if not other (custom) phases + ]; + + pnpmDeps = fetchPnpmDeps { + inherit (finalAttrs) pname version src; ++ pnpm = pnpm_10; + fetcherVersion = 3; + hash = "..."; + }; + }) +``` In case you are patching `package.json` or `pnpm-lock.yaml`, make sure to pass `finalAttrs.patches` to the function as well (i.e., `inherit (finalAttrs) patches`. -`pnpm.configHook` supports adding additional `pnpm install` flags via `pnpmInstallFlags` which can be set to a Nix string array: +`pnpmConfigHook` supports adding additional `pnpm install` flags via `pnpmInstallFlags` which can be set to a Nix string array: ```nix -{ pnpm }: - -stdenv.mkDerivation (finalAttrs: { - pname = "foo"; - version = "0-unstable-1980-01-01"; - - src = { +{ + # ... + pnpmDeps = fetchPnpmDeps { # ... + inherit (finalAttrs) pnpmInstallFlags; }; pnpmInstallFlags = [ "--shamefully-hoist" ]; - - pnpmDeps = pnpm.fetchDeps { inherit (finalAttrs) pnpmInstallFlags; }; -}) +} ``` #### Dealing with `sourceRoot` {#javascript-pnpm-sourceRoot} -If the pnpm project is in a subdirectory, you can just define `sourceRoot` or `setSourceRoot` for `fetchDeps`. -If `sourceRoot` is different between the parent derivation and `fetchDeps`, you will have to set `pnpmRoot` to effectively be the same location as it is in `fetchDeps`. +If the pnpm project is in a subdirectory, you can just define `sourceRoot` or `setSourceRoot` for `fetchPnpmDeps`. +If `sourceRoot` is different between the parent derivation and `fetchPnpmDeps`, you will have to set `pnpmRoot` to effectively be the same location as it is in `fetchPnpmDeps`. Assuming the following directory structure, we can define `sourceRoot` and `pnpmRoot` as follows: @@ -402,7 +439,7 @@ Assuming the following directory structure, we can define `sourceRoot` and `pnpm ```nix { # ... - pnpmDeps = pnpm.fetchDeps { + pnpmDeps = fetchPnpmDeps { # ... sourceRoot = "${finalAttrs.src.name}/frontend"; }; @@ -414,7 +451,7 @@ Assuming the following directory structure, we can define `sourceRoot` and `pnpm #### PNPM Workspaces {#javascript-pnpm-workspaces} -If you need to use a PNPM workspace for your project, then set `pnpmWorkspaces = [ "" "" ]`, etc, in your `pnpm.fetchDeps` call, +If you need to use a PNPM workspace for your project, then set `pnpmWorkspaces = [ "" "" ]`, etc, in your `fetchPnpmDeps` call, which will make PNPM only install dependencies for those workspace packages. For example: @@ -423,14 +460,14 @@ For example: { # ... pnpmWorkspaces = [ "@astrojs/language-server" ]; - pnpmDeps = pnpm.fetchDeps { - inherit (finalAttrs) pnpmWorkspaces; + pnpmDeps = fetchPnpmDeps { #... + inherit (finalAttrs) pnpmWorkspaces; }; } ``` -The above would make `pnpm.fetchDeps` call only install dependencies for the `@astrojs/language-server` workspace package. +The above would make `fetchPnpmDeps` call only install dependencies for the `@astrojs/language-server` workspace package. Note that you do not need to set `sourceRoot` to make this work. Usually, in such cases, you'd want to use `pnpm --filter= build` to build your project, as `npmHooks.npmBuildHook` probably won't work. A `buildPhase` based on the following example will probably fit most workspace projects: @@ -457,23 +494,23 @@ set `prePnpmInstall` to the right commands to run. For example: prePnpmInstall = '' pnpm config set dedupe-peer-dependents false ''; - pnpmDeps = pnpm.fetchDeps { + pnpmDeps = fetchPnpmDeps { inherit (finalAttrs) prePnpmInstall; # ... }; } ``` -In this example, `prePnpmInstall` will be run by both `pnpm.configHook` and by the `pnpm.fetchDeps` builder. +In this example, `prePnpmInstall` will be run by both `pnpmConfigHook` and by the `fetchPnpmDeps` builder. -#### PNPM `fetcherVersion` {#javascript-pnpm-fetcherVersion} +#### pnpm `fetcherVersion` {#javascript-pnpm-fetcherVersion} -This is the version of the output of `pnpm.fetchDeps`, if you haven't set it already, you can use `1` with your current hash: +This is the version of the output of `fetchPnpmDeps`, if you haven't set it already, you can use `1` with your current hash: ```nix { # ... - pnpmDeps = pnpm.fetchDeps { + pnpmDeps = fetchPnpmDeps { # ... fetcherVersion = 1; hash = "..."; # you can use your already set hash here @@ -486,7 +523,7 @@ After upgrading to a newer `fetcherVersion`, you need to regenerate the hash: ```nix { # ... - pnpmDeps = pnpm.fetchDeps { + pnpmDeps = fetchPnpmDeps { # ... fetcherVersion = 2; hash = "..."; # clear this hash and generate a new one @@ -494,7 +531,7 @@ After upgrading to a newer `fetcherVersion`, you need to regenerate the hash: } ``` -This variable ensures that we can make changes to the output of `pnpm.fetchDeps` without breaking existing hashes. +This variable ensures that we can make changes to the output of `fetchPnpmDeps` without breaking existing hashes. Changes can include workarounds or bug fixes to existing PNPM issues. ##### Version history {#javascript-pnpm-fetcherVersion-versionHistory} diff --git a/doc/release-notes/rl-2605.section.md b/doc/release-notes/rl-2605.section.md index 40a0566a9f8e..2314f939b856 100644 --- a/doc/release-notes/rl-2605.section.md +++ b/doc/release-notes/rl-2605.section.md @@ -54,6 +54,8 @@ If your SQLite database is corrupted, the migration might fail and require [manual intervention](https://github.com/louislam/uptime-kuma/issues/5281). See the [migration guide](https://github.com/louislam/uptime-kuma/wiki/Migration-From-v1-To-v2) for more information. +- `fetchPnpmDeps` and `pnpmConfigHook` were added as top-level attributes, replacing the now deprecated `pnpm.fetchDeps` and `pnpm.configHook` attributes. + - Added `dell-bios-fan-control` package and service. - We now use the upstream wrapper script for Gradle, supporting both the `JAVA_HOME` and `GRADLE_OPTS` environment variables. diff --git a/pkgs/development/tools/pnpm/fetch-deps/default.nix b/pkgs/build-support/node/fetch-pnpm-deps/default.nix similarity index 90% rename from pkgs/development/tools/pnpm/fetch-deps/default.nix rename to pkgs/build-support/node/fetch-pnpm-deps/default.nix index 4fb7c6d6d736..5bd934bdd6ab 100644 --- a/pkgs/development/tools/pnpm/fetch-deps/default.nix +++ b/pkgs/build-support/node/fetch-pnpm-deps/default.nix @@ -10,9 +10,8 @@ yq, zstd, }: - let - pnpm' = pnpm; + pnpmLatest = pnpm; supportedFetcherVersions = [ 1 # First version. Here to preserve backwards compatibility @@ -21,11 +20,11 @@ let ]; in { - fetchDeps = lib.makeOverridable ( + fetchPnpmDeps = lib.makeOverridable ( { hash ? "", pname, - pnpm ? pnpm', + pnpm ? pnpmLatest, pnpmWorkspaces ? [ ], prePnpmInstall ? "", pnpmInstallFlags ? [ ], @@ -50,15 +49,15 @@ in in # pnpmWorkspace was deprecated, so throw if it's used. assert (lib.throwIf (args ? pnpmWorkspace) - "pnpm.fetchDeps: `pnpmWorkspace` is no longer supported, please migrate to `pnpmWorkspaces`." + "fetchPnpmDeps: `pnpmWorkspace` is no longer supported, please migrate to `pnpmWorkspaces`." ) true; assert (lib.throwIf (fetcherVersion == null) - "pnpm.fetchDeps: `fetcherVersion` is not set, see https://nixos.org/manual/nixpkgs/stable/#javascript-pnpm-fetcherVersion." + "fetchPnpmDeps: `fetcherVersion` is not set, see https://nixos.org/manual/nixpkgs/stable/#javascript-pnpm-fetcherVersion." ) true; assert (lib.throwIf (!(builtins.elem fetcherVersion supportedFetcherVersions)) - "pnpm.fetchDeps `fetcherVersion` is not set to a supported value (${lib.concatStringsSep ", " (map toString supportedFetcherVersions)}), see https://nixos.org/manual/nixpkgs/stable/#javascript-pnpm-fetcherVersion." + "fetchPnpmDeps `fetcherVersion` is not set to a supported value (${lib.concatStringsSep ", " (map toString supportedFetcherVersions)}), see https://nixos.org/manual/nixpkgs/stable/#javascript-pnpm-fetcherVersion." ) true; stdenvNoCC.mkDerivation ( @@ -72,7 +71,7 @@ in cacert jq moreutils - args.pnpm or pnpm' + pnpm # from args yq zstd ]; @@ -176,7 +175,7 @@ in passthru = { inherit fetcherVersion; serve = callPackage ./serve.nix { - pnpm = args.pnpm or pnpm'; + inherit pnpm; # from args pnpmDeps = finalAttrs.finalPackage; }; }; @@ -190,10 +189,9 @@ in ) ); - configHook = makeSetupHook { + pnpmConfigHook = makeSetupHook { name = "pnpm-config-hook"; propagatedBuildInputs = [ - pnpm zstd ]; substitutions = { diff --git a/pkgs/development/tools/pnpm/fetch-deps/pnpm-config-hook.sh b/pkgs/build-support/node/fetch-pnpm-deps/pnpm-config-hook.sh similarity index 91% rename from pkgs/development/tools/pnpm/fetch-deps/pnpm-config-hook.sh rename to pkgs/build-support/node/fetch-pnpm-deps/pnpm-config-hook.sh index 2532e5d465c1..66ea5026d72c 100644 --- a/pkgs/development/tools/pnpm/fetch-deps/pnpm-config-hook.sh +++ b/pkgs/build-support/node/fetch-pnpm-deps/pnpm-config-hook.sh @@ -12,6 +12,13 @@ pnpmConfigHook() { exit 1 fi + if ! command -v "pnpm" &> /dev/null; then + echo "Error: 'pnpm' binary not found in PATH. Consider adding 'pkgs.pnpm' to 'nativeBuildInputs'." >&2 + exit 1 + fi + + echo "Found 'pnpm' with version '$(pnpm --version)'" + fetcherVersion=$(cat "${pnpmDeps}/.fetcher-version" || echo 1) echo "Using fetcherVersion: $fetcherVersion" diff --git a/pkgs/development/tools/pnpm/fetch-deps/serve.nix b/pkgs/build-support/node/fetch-pnpm-deps/serve.nix similarity index 100% rename from pkgs/development/tools/pnpm/fetch-deps/serve.nix rename to pkgs/build-support/node/fetch-pnpm-deps/serve.nix diff --git a/pkgs/development/tools/pnpm/generic.nix b/pkgs/development/tools/pnpm/generic.nix index 626849d7b680..e200d8debcd4 100644 --- a/pkgs/development/tools/pnpm/generic.nix +++ b/pkgs/development/tools/pnpm/generic.nix @@ -2,7 +2,7 @@ lib, stdenvNoCC, writeScript, - callPackages, + fetchPnpmDeps, fetchurl, installShellFiles, nodejs, @@ -11,6 +11,7 @@ version, hash, buildPackages, + pnpmConfigHook, }: let majorVersion = lib.versions.major version; @@ -71,12 +72,20 @@ stdenvNoCC.mkDerivation (finalAttrs: { passthru = let - fetchDepsAttrs = callPackages ./fetch-deps { - pnpm = buildPackages."pnpm_${lib.versions.major version}"; - }; + pnpm' = buildPackages."pnpm_${lib.versions.major version}"; in { - inherit (fetchDepsAttrs) fetchDeps configHook; + fetchDeps = + { ... }@args: + fetchPnpmDeps args + // { + pnpm = pnpm'; + }; + configHook = pnpmConfigHook.overrideAttrs (prevAttrs: { + propagatedBuildInputs = prevAttrs.propagatedBuildInputs or [ ] ++ [ + pnpm' + ]; + }); inherit majorVersion; tests.version = lib.optionalAttrs withNode ( diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 5d751f8a13b1..e651b36d1f30 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -3606,6 +3606,11 @@ with pkgs; ; pnpm = pnpm_10; + inherit (callPackages ../build-support/node/fetch-pnpm-deps { }) + fetchPnpmDeps + pnpmConfigHook + ; + po4a = perlPackages.Po4a; podman-compose = python3Packages.callPackage ../applications/virtualization/podman-compose { };