pnpm 12.4.0 → 12.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,107 @@
1
1
  # pnpm
2
2
 
3
+ ## 12.4.1
4
+
5
+ pnpm 12.4.1 fixes installs that failed on filesystems refusing hard links or clones, on Android, and under `nodeLinker: hoisted`. Repeat installs are faster.
6
+
7
+ ### Patch Changes
8
+
9
+ #### Installing packages
10
+
11
+ - `pnpm install` no longer fails with `Operation not permitted` when the filesystem refuses a hard link or a copy-on-write clone [#14722](https://github.com/pnpm/pnpm/issues/14722). Under `packageImportMethod: auto` and `clone-or-copy`, pnpm copies the file instead. EdenFS checkouts, which have no hard links, and rootless containers, which refuse the clone syscall, both hit this. An explicit `packageImportMethod: hardlink` or `clone` still reports the error.
12
+
13
+ pnpm also copies a package file whose store entry has reached the filesystem's limit on names for one file, 1024 on NTFS and 65000 on ext4. Such a file failed the install under `packageImportMethod: hardlink`, and under `auto` it stopped pnpm hard linking for the rest of the install.
14
+
15
+ - `pnpm install` no longer writes a package file through a symlink left at the path it is importing to. Copying such a file overwrote whatever the link pointed at, and created that file when the link pointed nowhere. An executable package file also made the link's target executable.
16
+
17
+ - Fixed `pnpm install` and `pnpm dlx` on Android. Registry requests crashed because pnpm found no system CA certificates, so pnpm uses bundled ones there [#14777](https://github.com/pnpm/pnpm/issues/14777). Imports also failed with "Permission denied" on filesystems that deny hard links and reflinks, and now fall back to copying [#14780](https://github.com/pnpm/pnpm/issues/14780).
18
+
19
+ - `pnpm install` no longer fails with "Invalid cross-device link" while preserving a package's nested `node_modules` directory during a Docker build [#14758](https://github.com/pnpm/pnpm/issues/14758).
20
+
21
+ - `pnpm install` no longer fails on a package tarball that carries a file at the archive root, such as the `._*` entries macOS `tar` adds [#14701](https://github.com/pnpm/pnpm/issues/14701). The file is installed at the root of the package.
22
+
23
+ A `file:` tarball packed without the usual `package/` directory is now recorded under the name and version from its own `package.json`. It was recorded under the alias the dependency was given, at version 0.0.0.
24
+
25
+ - Under `nodeLinker: hoisted`, `pnpm install` no longer re-imports packages that are already in place. A repeat install replaced the whole `node_modules` tree and reported `Packages: +N`. A package is still imported when its directory is missing, when its `package.json` no longer carries the installed version, when it is a `file:` dependency, and when it is patched. Lifecycle scripts no longer run again for a package left in place, and `pnpm rebuild` and a change to `allowBuilds` still reach it.
26
+
27
+ - `pnpm install` now runs a dependency's build scripts again when its side-effects cache entry has no files to restore [#14717](https://github.com/pnpm/pnpm/issues/14717). Such builds were skipped and nothing was put in their place, so a script whose whole effect lands outside its own package directory, such as a git hook installer, never took effect. pnpm no longer publishes empty artifacts to the shared side-effects cache either.
28
+
29
+ #### Resolving and linking dependencies
30
+
31
+ - `pnpm install`, `pnpm add`, and `pnpm dedupe` now apply `ignoredOptionalDependencies` [#14729](https://github.com/pnpm/pnpm/issues/14729). Matching optional dependencies are left out of the lockfile and are not installed. pnpm 12 installed them whenever it resolved dependencies from scratch.
32
+
33
+ - `pnpm install` no longer links a transitive dependency to a workspace package when `linkWorkspacePackages` is `true` and the dependency is declared with a plain version range [#14781](https://github.com/pnpm/pnpm/issues/14781). Enabling `preferWorkspacePackages` does not change this. Set `linkWorkspacePackages: deep` to link them.
34
+
35
+ - `pnpm install` no longer leaves dangling dependency links in workspace packages located above the workspace root [#14726](https://github.com/pnpm/pnpm/issues/14726).
36
+
37
+ - `pnpm install` and `pnpm add` no longer leave a dangling symlink in `node_modules` when a project starts depending directly on a package that the lockfile holds only as a transitive dependency with resolved peer dependencies [#14714](https://github.com/pnpm/pnpm/issues/14714).
38
+
39
+ - `pnpm dedupe` now keeps a compatible auto-installed peer when another workspace project depends on a newer major [#14697](https://github.com/pnpm/pnpm/issues/14697). Repeated runs alternated between compatible and incompatible peer versions.
40
+
41
+ - `pnpm peers check` no longer reports a peer dependency declared as `workspace:^`, `workspace:~`, or a bare `workspace:` as unmet [#14770](https://github.com/pnpm/pnpm/issues/14770). pnpm reported these as unmet whatever version the linked workspace project supplied.
42
+
43
+ #### Performance
44
+
45
+ - Sped up repeat installs [#14540](https://github.com/pnpm/pnpm/issues/14540). pnpm checks the store's files only for the packages it links into `node_modules`, instead of every package in the lockfile. Creating the command shims in `node_modules/.bin` makes about 1,500 fewer filesystem calls in a 76 project workspace. Installs that use the global virtual store read their slot paths from the cache directory instead of deriving them every time. Verifying a large lockfile also allocates less memory.
46
+
47
+ - Sped up `pnpm install` in Cargo workspaces with many member crates. Repeated installs reuse verified Cargo checksum metadata.
48
+
49
+ - Installing several packages from the same Git repository and commit now downloads the source once per install [#14725](https://github.com/pnpm/pnpm/issues/14725). Each package still runs its prepare scripts in its own copy of the checkout.
50
+
51
+ #### Running scripts and tasks
52
+
53
+ - pnpm now passes Ctrl+C on to the script or command it started and waits for it to shut down [#14723](https://github.com/pnpm/pnpm/issues/14723). pnpm exited first, so a script that was still writing landed on the shell prompt.
54
+
55
+ - `pnpm run "/pattern/" --no-bail` now lets every matched script finish after one of them fails [#14718](https://github.com/pnpm/pnpm/issues/14718). The command exits with `ERR_PNPM_RUN_FAILED`, and its message lists the scripts that failed in the order they were selected.
56
+
57
+ - `pnpm pipeline` no longer fails on a project that tracks a symlink, such as a `CLAUDE.md` pointing at `AGENTS.md` [#14692](https://github.com/pnpm/pnpm/issues/14692). Changing a symlinked input's target invalidates that task's cache, and `pnpm pipeline --no-cache` no longer hashes task inputs.
58
+
59
+ #### Commands
60
+
61
+ - `pnpm add -g`, `pnpm update -g`, and `pnpm remove -g` no longer change global bins or install directories after reading only part of an installed package group [#13796](https://github.com/pnpm/pnpm/issues/13796). If any declared package manifest is missing, malformed, or unreadable, pnpm now fails before it activates or removes anything and leaves the existing global installation intact.
62
+
63
+ - `pnpm dedupe` now processes every workspace project by default, including workspaces that keep a separate lockfile per project [#14732](https://github.com/pnpm/pnpm/issues/14732). Workspace filters select which projects it processes, and `--fail-if-no-match` exits with an error when no project matches.
64
+
65
+ - `pnpm update <name>@<version>` now keeps the range operator the manifest declares [#14745](https://github.com/pnpm/pnpm/issues/14745). Running `pnpm update react@19.3.0` on `"react": "^19.2.8"` writes `"react": "^19.3.0"`. A `jsr:` entry keeps its `jsr:` prefix, and a plain `pnpm update` now moves a `jsr:` range the way it moves an npm range.
66
+
67
+ - `pnpm --filter` directory selectors now support `?` wildcards and character classes such as `[ab]`. A `*` or `?` wildcard no longer selects a directory whose name starts with a dot, as on pnpm 11.
68
+
69
+ - `pnpm deploy --legacy` now prefers the dependency versions pinned in the source workspace lockfile when they still satisfy the deployed project's range [#13857](https://github.com/pnpm/pnpm/issues/13857).
70
+
71
+ - `pnpm sbom` now leaves out a package's author field when the manifest author name is empty or contains only whitespace [#14685](https://github.com/pnpm/pnpm/issues/14685). In a filtered or split workspace run, only a project with no `author` field inherits the workspace root's author.
72
+
73
+ `pnpm sbom --sbom-format spdx` now writes `creationInfo.created` with whole seconds, such as `2026-09-08T10:38:21Z` [#14684](https://github.com/pnpm/pnpm/issues/14684). The fractional seconds it carried were rejected by strict SPDX consumers.
74
+
75
+ #### Configuration
76
+
77
+ - The `updateConfig` pnpmfile hook now receives the resolved configuration, including settings that came from `.npmrc`, the command line, or a default [#14676](https://github.com/pnpm/pnpm/issues/14676). Scoped registries are reported under `registriesByScope`, and a hook may rewrite that map to change where packages are fetched from. Registry credentials are reported under `configByUri`, as pnpm 11 reports them. An unset setting is left out rather than reported as `null`.
78
+
79
+ - `pnpm audit --fix` and the `minimumReleaseAgeStrict` approval prompt now keep the comments in `minimumReleaseAgeExclude` when they append an entry to it in `pnpm-workspace.yaml`. The rest of the list is left as written, and the `trustPolicyExcludePrune` and `minimumReleaseAgeExcludePrune` cleanups keep the comments of the entries they retain.
80
+
81
+ `pnpm install` and `pnpm dedupe` now run those cleanups too [#14759](https://github.com/pnpm/pnpm/issues/14759). Only `pnpm add`, `pnpm update`, and `pnpm remove` pruned the entries that the freshly written lockfile no longer resolves.
82
+
83
+ - `pnpm config set --global node-download-mirrors` no longer rejects the key [#13611](https://github.com/pnpm/pnpm/issues/13611). The global config file already accepted `nodeDownloadMirrors`, but the command refused to write it.
84
+
85
+ - `NO_PROXY` entries that start with a dot, such as `.npmjs.org`, now bypass the proxy for the domain and its subdomains [#14686](https://github.com/pnpm/pnpm/issues/14686).
86
+
87
+ - pnpm no longer creates a project `pnpm-lock.yaml` when `devEngines.packageManager.onFail` is `download` and lockfile writing is off through `lockfile: false` or `--no-lockfile` [#14728](https://github.com/pnpm/pnpm/issues/14728). pnpm still switches to the pinned version.
88
+
89
+ - pnpm now writes `node_modules/.package-map.json` only when `nodeExperimentalPackageMap` is enabled. Nothing reads the file without that setting, and an install that stops writing the map removes the one a previous install left.
90
+
91
+ #### Windows
92
+
93
+ - `pnpm pipeline` no longer fails with intermittent access denied errors when concurrent tasks save their cache entries on Windows.
94
+
95
+ - Windows filesystem operations now retry permission errors for up to one second [#14682](https://github.com/pnpm/pnpm/issues/14682). A permanent permission error delayed the failure by a minute. Sharing and lock violations keep their one minute retry budget.
96
+
97
+ #### Messages and output
98
+
99
+ - pnpm now warns when the root `package.json` declares a non-empty `workspaces` array and the project has no `pnpm-workspace.yaml` [#2255](https://github.com/pnpm/pnpm/issues/2255). Such an install linked no project and said nothing about why.
100
+
101
+ - `ERR_PNPM_PACKAGE_MANAGER_REMOVE_MODULES_DIR` now names the file or directory in `node_modules` that pnpm could not clean up. It reported only the underlying OS error, such as "Access is denied (os error 5)".
102
+
103
+ - `pnpm --help` no longer describes pnpm as experimental.
104
+
3
105
  ## 12.4.0
4
106
 
5
107
  ### Minor Changes
@@ -1,9 +1,9 @@
1
1
  {
2
- "lastValidatedTimestamp": 1788864536446,
2
+ "lastValidatedTimestamp": 1789057805684,
3
3
  "projects": {
4
4
  "/home/runner/_work/pnpm/pnpm/pnpm/npm/pnpm/temp-deploy": {
5
5
  "name": "pacquet",
6
- "version": "12.4.0"
6
+ "version": "12.4.1"
7
7
  }
8
8
  },
9
9
  "pnpmfiles": [],
@@ -28,7 +28,7 @@
28
28
  "@commitlint/prompt-cli": "^21.2.2",
29
29
  "@cyclonedx/cyclonedx-library": "10.2.0",
30
30
  "@eslint/js": "^10.0.1",
31
- "@inquirer/prompts": "^8.7.1",
31
+ "@inquirer/prompts": "^8.7.2",
32
32
  "@jest/globals": "30.4.1",
33
33
  "@npm/types": "^2.1.0",
34
34
  "@openpgp/web-stream-tools": "0.3.1",
@@ -48,7 +48,7 @@
48
48
  "@pnpm/tabtab": "^0.5.4",
49
49
  "@pnpm/tgz-fixtures": "0.0.0",
50
50
  "@reflink/reflink": "0.1.19",
51
- "@rushstack/worker-pool": "0.7.25",
51
+ "@rushstack/worker-pool": "0.7.26",
52
52
  "@stylistic/eslint-plugin": "^5.10.0",
53
53
  "@types/adm-zip": "^0.5.8",
54
54
  "@types/archy": "0.0.36",
@@ -87,7 +87,7 @@
87
87
  "@types/write-file-atomic": "^4.0.3",
88
88
  "@types/yarnpkg__lockfile": "^1.1.9",
89
89
  "@types/zkochan__table": "npm:@types/table@6.3.2",
90
- "@typescript-eslint/utils": "^8.69.0",
90
+ "@typescript-eslint/utils": "^8.70.0",
91
91
  "@typescript/native-preview": "7.0.0-dev.20260707.2",
92
92
  "@yarnpkg/core": "4.9.1",
93
93
  "@yarnpkg/extensions": "2.0.7",
@@ -246,7 +246,7 @@
246
246
  "tree-kill": "^1.2.2",
247
247
  "ts-jest-resolver": "2.0.1",
248
248
  "typescript": "6.0.3",
249
- "typescript-eslint": "^8.69.0",
249
+ "typescript-eslint": "^8.70.0",
250
250
  "undici": "^7.29.0",
251
251
  "unified": "^11.0.5",
252
252
  "validate-npm-package-name": "7.0.2",
@@ -319,6 +319,7 @@
319
319
  "nodeLinker": "hoisted",
320
320
  "optional": true,
321
321
  "patchedDependencies": {
322
+ "adm-zip@0.6.0": "../../../../__patches__/adm-zip@0.6.0.patch",
322
323
  "graceful-fs@4.2.11": "../../../../__patches__/graceful-fs@4.2.11.patch",
323
324
  "normalize-registry-url@2.0.1": "../../../../__patches__/normalize-registry-url@2.0.1.patch"
324
325
  },
@@ -330,10 +331,8 @@
330
331
  "trustPolicyExclude": [
331
332
  "@pnpm/*",
332
333
  "@yarnpkg/libzip@3.2.2",
333
- "fastq@1.20.2",
334
334
  "pnpm",
335
335
  "rxjs@7.8.2",
336
- "tinyexec@1.2.2",
337
336
  "undici-types@6.21.0"
338
337
  ],
339
338
  "trustPolicyIgnoreAfter": 10080
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "./dist/node_modules/node-gyp/gyp/gyp"
10
10
  ]
11
11
  },
12
- "version": "12.4.0",
12
+ "version": "12.4.1",
13
13
  "description": "Fast, disk space efficient package manager",
14
14
  "keywords": [
15
15
  "pnpm",
@@ -46,20 +46,20 @@
46
46
  "THIRD-PARTY-NOTICES.md"
47
47
  ],
48
48
  "optionalDependencies": {
49
- "@pnpm/exe.win32-x64": "12.4.0",
50
- "@pnpm/exe.win32-arm64": "12.4.0",
51
- "@pnpm/exe.darwin-x64": "12.4.0",
52
- "@pnpm/exe.darwin-arm64": "12.4.0",
53
- "@pnpm/exe.linux-x64": "12.4.0",
54
- "@pnpm/exe.linux-arm64": "12.4.0",
55
- "@pnpm/exe.linux-riscv64": "12.4.0",
56
- "@pnpm/exe.linux-ppc64": "12.4.0",
57
- "@pnpm/exe.linux-s390x": "12.4.0",
58
- "@pnpm/exe.linux-x64-musl": "12.4.0",
59
- "@pnpm/exe.linux-arm64-musl": "12.4.0",
60
- "@pnpm/exe.freebsd-x64": "12.4.0",
61
- "@pnpm/exe.android-arm64": "12.4.0",
62
- "@pnpm/exe.android-x64": "12.4.0"
49
+ "@pnpm/exe.win32-x64": "12.4.1",
50
+ "@pnpm/exe.win32-arm64": "12.4.1",
51
+ "@pnpm/exe.darwin-x64": "12.4.1",
52
+ "@pnpm/exe.darwin-arm64": "12.4.1",
53
+ "@pnpm/exe.linux-x64": "12.4.1",
54
+ "@pnpm/exe.linux-arm64": "12.4.1",
55
+ "@pnpm/exe.linux-riscv64": "12.4.1",
56
+ "@pnpm/exe.linux-ppc64": "12.4.1",
57
+ "@pnpm/exe.linux-s390x": "12.4.1",
58
+ "@pnpm/exe.linux-x64-musl": "12.4.1",
59
+ "@pnpm/exe.linux-arm64-musl": "12.4.1",
60
+ "@pnpm/exe.freebsd-x64": "12.4.1",
61
+ "@pnpm/exe.android-arm64": "12.4.1",
62
+ "@pnpm/exe.android-x64": "12.4.1"
63
63
  },
64
64
  "scripts": {
65
65
  "preinstall": "node install.js",