pnpm 12.0.0-rc.6 → 12.0.0-rc.7

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,128 @@
1
1
  # pnpm
2
2
 
3
+ ## 12.0.0-rc.7
4
+
5
+ ### Minor Changes
6
+
7
+ - `node_modules/.modules.yaml` no longer records the registries an install resolved from, and the recorded copy is dropped from the file on the first install that rewrites it.
8
+
9
+ It dated from the lockfile format that spelled a dependency's path relative to its registry, where reading an installed tree meant knowing the registries it was installed with. Dependency paths have not carried a registry for several major versions, and the recorded copy outlived its use: `pnpm list`, `pnpm why`, and single-project installs preferred it over the project's own configuration, so a project whose registry had changed since its last install was still read through the old one.
10
+
11
+ They now use the configured registries, like every other command already did.
12
+
13
+ - When `enableGlobalVirtualStore` is on, every process pnpm spawns for the project (`pnpm run`, `pnpm exec`, lifecycle scripts) now receives a `NODE_PATH` pointing at the project's hoisted `node_modules`, plus a `NODE_OPTIONS` `--import` flag that registers a resolve hook restoring `NODE_PATH` lookups for ESM imports. Dependencies that import undeclared ("phantom") packages keep resolving under the global virtual store — for both CommonJS and ESM — without installing the `@pnpm/plugin-esm-node-path` config dependency [pnpm/pnpm#9618](https://github.com/pnpm/pnpm/issues/9618). Tools run by `pnpm dlx` resolve such dependencies too: the JS CLI passes them the same environment, while the Rust CLI's dlx cache is self-contained, so its layout already exposes them.
14
+
15
+ - A registry can now declare that its abbreviated metadata carries the `time` field, so `resolutionMode: time-based` reads the full metadata document only from the registries that need it:
16
+
17
+ ```yaml
18
+ resolutionMode: time-based
19
+ registries:
20
+ https://npm.internal.example/:
21
+ supportsTimeField: true
22
+ ```
23
+
24
+ `registry.npmjs.org` omits `time` from abbreviated metadata, so a time-based resolution has to fall back to the much larger full document. That fallback used to be all-or-nothing: `registrySupportsTimeField` answered for every registry at once, so a project resolving from both the public registry and a Verdaccio instance either paid for full metadata everywhere or claimed a `time` field npmjs does not serve. The answer is now per registry, and `registrySupportsTimeField` remains the answer for every registry that does not declare one.
25
+
26
+ The declaration is also sent to a pnpr server, which applies it to the resolution it runs on the client's behalf.
27
+
28
+ - A pnpr resolve request now carries the client's registries the way the `registries` setting declares them — keyed by URL, with the scopes routed to each, the bare-specifier prefix each answers to, and each one's `serverType` — in place of the prefix map it used to send.
29
+
30
+ The server routes them through the same inversion the config reader runs, so a pnpr-served install resolves a scoped dependency from the registry that scope is routed to, which it previously could not: only the default registry and the prefix-addressed ones reached the server. A declared `serverType` reaches it too, so the tarball URLs pnpr omits from the lockfile match the ones the client reconstructs.
31
+
32
+ Built-in scope routes the project has not pointed elsewhere are not declared, so a pnpr server's allowlist is not asked about `npm.jsr.io` on requests that resolve no JSR package.
33
+
34
+ A registry a request only declares is no longer refused up front for being off the server's allowlist — a client describes its whole configuration, including scopes a given resolve never reaches, so a stray `@scope:registry` in a developer's `~/.npmrc` no longer fails every install against a pnpr server that does not serve it. The boundary moves to the fetch itself: an origin the resolve does reach is refused before the request leaves the server, with the same message.
35
+
36
+ This changes the resolve and verify-lockfile request bodies. A pnpr server and its clients have to be on matching versions; the protocol is still experimental and unversioned.
37
+
38
+ - A resolve request now carries the client's `resolutionMode`, so an install delegated to a pnpr server picks versions the way the client would. `time-based` and `lowest-direct` reached the server as nothing at all, leaving it on its `highest` default: the returned lockfile pinned the highest satisfying version of every dependency, and the setting appeared to be ignored.
39
+
40
+ This adds a field to the resolve request body. A server older than its client ignores it and keeps resolving `highest`; the protocol is still experimental and unversioned.
41
+
42
+ - The `registries` setting now declares a registry once, keyed by its URL, with everything about that registry in the entry: how it lays out tarball URLs, the scopes routed to it, and the bare-specifier prefix it answers to.
43
+
44
+ ```yaml
45
+ registries:
46
+ https://artifactory.example.com/artifactory/api/npm/npm-virtual/:
47
+ serverType: artifactory
48
+ scopes: ['@acme', '@acme-internal']
49
+ prefix: work
50
+ ```
51
+
52
+ - **`serverType`** tells pnpm how the registry lays out its tarball URLs, which decides whether a URL can be omitted from `pnpm-lock.yaml`:
53
+ - **undeclared** (the default) — strict. Only the exact canonical URL is treated as reconstructible.
54
+ - **`npm`** — the registry behaves like `registry.npmjs.org`, which also serves a scoped package from its percent-encoded path. Declare this for a faithful mirror or caching proxy of the public registry so its tarball URLs can be omitted too.
55
+ - **`artifactory`** — JFrog Artifactory repeats the scope in a scoped package's tarball filename (`@acme/widget/-/@acme/widget-1.0.0.tgz`) where the npm registry strips it (`@acme/widget/-/widget-1.0.0.tgz`). Declaring it lets pnpm rebuild that URL, so it is omitted from `pnpm-lock.yaml` instead of being written out for every scoped package [pnpm/get-npm-tarball-url#16](https://github.com/pnpm/get-npm-tarball-url/issues/16).
56
+ - **`scopes`** lists the `@`-prefixed scopes that resolve from this registry. A bare `'@'` is the scope-less default registry, the one the `registry` setting names.
57
+ - **`prefix`** is the alias a dependency addresses this registry by, as in `"foo": "work:^1.0.0"`.
58
+
59
+ The layout is never inferred from the registry URL, so nothing changes unless you declare it; `registry.npmjs.org` continues to behave as `npm` without being declared. Because the lockfile depends on `serverType`, it is read from `pnpm-workspace.yaml` only — a `serverType` in the global `config.yaml` is ignored, so one developer's machine cannot shape a lockfile their collaborators read back with a different layout. Credentials are rejected in this setting, in a key as well as in a field, and still belong in `.npmrc`. An entry that routes nothing to itself and matches no configured registry is reported as a warning rather than silently ignored.
60
+
61
+ ### Migrating
62
+
63
+ The older `registries` shape, a map of `<scope>: <url>` strings, still works and needs no change:
64
+
65
+ ```yaml
66
+ registries:
67
+ '@acme': https://npm.acme.example/
68
+ ```
69
+
70
+ `namedRegistries` is deprecated in favor of the `prefix` field, and is still read for prefixes `registries` does not declare.
71
+
72
+ `toLockfileResolution` and `isCanonicalRegistryTarballUrl` now take their registry and layout as an options object rather than positional arguments, so `@pnpm/lockfile.utils` and `@pnpm/resolving.tarball-url` get a major bump.
73
+
74
+ - Added `virtualStoreType`, which names where the virtual store lives — one store per machine, or one per project:
75
+
76
+ ```yaml
77
+ virtualStoreType: global # or: project
78
+ ```
79
+
80
+ It is the canonical spelling of `enableGlobalVirtualStore`, which keeps working. When a project sets both, `virtualStoreType` wins. It can also be set through `PNPM_CONFIG_VIRTUAL_STORE_TYPE` and read back with `pnpm config get virtualStoreType`. The default is unchanged — `project`, so the shared store stays opt-in.
81
+
82
+ The setting is independent of `nodeLinker`. `isolated` and `pnp` both work with either store type, and `hoisted` writes no virtual store at all, so it is unaffected.
83
+
84
+ ### Patch Changes
85
+
86
+ - Fixed `pnpm patch-commit` in project and edit paths containing non-ASCII characters.
87
+
88
+ - Fixed `404` errors when installing from a registry that serves scoped packages only from a percent-encoded path, such as GitHub Enterprise Server. Outside `registry.npmjs.org`, a tarball URL that encodes the scope separator as `%2f` or `%2F` is no longer mistaken for one that pnpm can rebuild from the package name, version, and registry, so it is kept in `pnpm-lock.yaml` and requested verbatim on the next install [#13534](https://github.com/pnpm/pnpm/issues/13534).
89
+
90
+ - Fixed an inconsistency where `minimumReleaseAgeExclude` (and `trustPolicyExclude`) wildcard/bare-name rules behaved differently in the evaluator and normalizer. A bare rule now consistently evaluates as matching every version, preventing unexpected behavior and silent widening of version policy exemptions when pnpm rewrites the workspace manifest [pnpm/pnpm#13725](https://github.com/pnpm/pnpm/issues/13725).
91
+
92
+ - Fixed `pnpm update --global --latest` failing with a 404 error when a globally installed package was not added from the registry by name. Packages installed from a local path (`link:`/`file:`), a git repository, a tarball URL, an `npm:` alias, or a named registry now keep their spec during a global update instead of being looked up by name in the default registry. See pnpm/pnpm#12854.
93
+
94
+ - `pnpm outdated` and `pnpm update --interactive` now dereference `catalog:` specifiers before querying the registry. A catalog entry that is an npm alias (`'@types/zkochan__table': npm:@types/table@6.3.2`) no longer fails with `ERR_PNPM_OUTDATED_REGISTRY_ERROR` for the alias key, and `pnpm outdated --compatible` compares against the range the catalog holds instead of skipping the dependency.
95
+
96
+ - A failed packument request now reports the status the registry returned (`404 Not Found`) instead of "error decoding response body".
97
+
98
+ - Installs with a cold cache are significantly faster: lockfile verification no longer delays resolution or downloads and re-checks far less data over the network, and downloaded packages are linked while the remaining downloads are still in flight.
99
+
100
+ - Fixed `pnpm` installs using pnpr to honor the client's `autoInstallPeers`, `dedupePeers`, and `excludeLinksFromLockfile` settings [pnpm/pnpm#13389](https://github.com/pnpm/pnpm/issues/13389).
101
+
102
+ - The three registry lookups are now named for what they are keyed by, so that none of them is called `registries` — a name the `registries` setting itself has taken:
103
+
104
+ | before | after |
105
+ |---|---|
106
+ | `Config.registries` | `Config.registriesByScope` |
107
+ | `Config.namedRegistries` | `Config.registriesByPrefix` |
108
+ | `Config.registryOptions` | `Config.registryOptionsByUrl` |
109
+
110
+ The same rename applies to the `RegistryContext` fields, the `Registries` and `NamedRegistries` types (now `RegistriesByScope` and `RegistriesByPrefix`), `normalizeRegistries` / `normalizeNamedRegistries` (now `normalizeRegistriesByScope` / `normalizeRegistriesByPrefix`), and the `BUILTIN_NAMED_REGISTRIES` constant (now `BUILTIN_REGISTRIES_BY_PREFIX`).
111
+
112
+ This is an internal rename: no setting, error code, lockfile field, or `.pnpmfile.cjs` hook field changes. A `preResolution` hook still reads `ctx.registries`, which is the name pacquet passes as well. The `registries` and `namedRegistries` settings are read under the names users write them.
113
+
114
+ The pnpr resolve request sends `registriesByPrefix` where it sent `namedRegistries`. A pnpr server and its clients must be on matching versions, which is already the case for an experimental server.
115
+
116
+ - An install that had to re-hash store files to verify them now reports it. If that cost more than a second, it says how long — `The integrity of N files was checked in 2.5s.` — and if it was quick but covered more than a thousand files, it names the cause instead: their timestamps changed since the store recorded them, which a backup tool, an antivirus scan or a copied store can do.
117
+
118
+ - Installs are faster in workspaces that declare inter-workspace dependencies with plain ranges (`"*"`, `"^1.2.3"`) rather than the `workspace:` protocol. With `preferWorkspacePackages` enabled, linking such a dependency no longer makes a registry request that cannot change the outcome — and workspace packages that were never published no longer cost a 404 on every install.
119
+
120
+ - An override change is now absorbed by the fast lockfile update even when another, unchanged override uses the `catalog:` protocol. Previously any `catalog:`-valued override forced a full re-resolution whenever the override list changed, which could move unrelated packages in the lockfile (for example after `pnpm audit --fix` added an override).
121
+
122
+ - Reduced peak memory usage when installing large packages. A tarball whose compressed size is at least 16 MiB, or whose registry-reported unpacked size is at least 64 MiB, is now extracted by streaming the decompression directly into the content-addressable store instead of materializing the whole decompressed archive in memory, and its large files are hashed and written to the store incrementally.
123
+
124
+ - `pnpm why` and `pnpm list` no longer print stray `[90m`-style codes in their trees when the terminal supports colors. The bolded labels — the searched package in `pnpm why`, the project header and the matched package in `pnpm list` — dropped the escape byte of the styles they already carried, leaving the color codes as visible text.
125
+
3
126
  ## 12.0.0-rc.6
4
127
 
5
128
  ### Minor Changes
@@ -1,9 +1,9 @@
1
1
  {
2
- "lastValidatedTimestamp": 1786812811685,
2
+ "lastValidatedTimestamp": 1787046162762,
3
3
  "projects": {
4
4
  "/home/runner/_work/pnpm/pnpm/pnpm/npm/pnpm/temp-deploy": {
5
5
  "name": "pacquet",
6
- "version": "12.0.0-rc.6"
6
+ "version": "12.0.0-rc.7"
7
7
  }
8
8
  },
9
9
  "pnpmfiles": [],
@@ -22,9 +22,9 @@
22
22
  "default": {
23
23
  "@babel/core": "^7.29.7",
24
24
  "@babel/plugin-transform-explicit-resource-management": "^7.29.7",
25
- "@commitlint/cli": "^21.2.1",
26
- "@commitlint/config-conventional": "^21.2.0",
27
- "@commitlint/prompt-cli": "^21.2.0",
25
+ "@commitlint/cli": "^21.2.2",
26
+ "@commitlint/config-conventional": "^21.2.2",
27
+ "@commitlint/prompt-cli": "^21.2.2",
28
28
  "@cyclonedx/cyclonedx-library": "10.1.1",
29
29
  "@eslint/js": "^10.0.1",
30
30
  "@inquirer/prompts": "^8.5.2",
@@ -47,7 +47,7 @@
47
47
  "@pnpm/tabtab": "^0.5.4",
48
48
  "@pnpm/tgz-fixtures": "0.0.0",
49
49
  "@reflink/reflink": "0.1.19",
50
- "@rushstack/worker-pool": "0.7.22",
50
+ "@rushstack/worker-pool": "0.7.23",
51
51
  "@stylistic/eslint-plugin": "^5.10.0",
52
52
  "@types/adm-zip": "^0.5.8",
53
53
  "@types/archy": "0.0.36",
@@ -184,7 +184,7 @@
184
184
  "npm-packlist": "10.0.4",
185
185
  "npm-registry-fetch": "^19.0.0",
186
186
  "object-hash": "3.0.0",
187
- "open": "^11.0.0",
187
+ "open": "^11.0.1",
188
188
  "openpgp": "^6.3.1",
189
189
  "p-defer": "^4.0.1",
190
190
  "p-every": "^2.0.0",
@@ -278,7 +278,60 @@
278
278
  "injectWorkspacePackages": false,
279
279
  "linkWorkspacePackages": false,
280
280
  "minimumReleaseAge": 1440,
281
+ "minimumReleaseAgeExclude": [
282
+ "@pnpm/*",
283
+ "@rushstack/worker-pool@0.7.18",
284
+ "@zkochan/*",
285
+ "better-path-resolve",
286
+ "body-parser@2.2.1",
287
+ "can-link",
288
+ "can-write-to-dir",
289
+ "cmd-extension",
290
+ "comver-to-semver",
291
+ "dir-is-case-sensitive",
292
+ "esbuild@0.28.1",
293
+ "@esbuild/*",
294
+ "express@4.22.1",
295
+ "glob@11.1.0",
296
+ "handlebars@4.7.9",
297
+ "is-inner-link",
298
+ "is-subdir",
299
+ "jws@3.2.3",
300
+ "lodash@4.17.23",
301
+ "make-empty-dir",
302
+ "normalize-registry-url",
303
+ "p-map-values",
304
+ "parse-npm-tarball-url@5.0.0",
305
+ "path-absolute",
306
+ "path-temp",
307
+ "pnpm",
308
+ "preferred-pm",
309
+ "promise-share",
310
+ "qs@6.14.2 || 6.15.2",
311
+ "read-ini-file",
312
+ "read-json5-file",
313
+ "read-yaml-file",
314
+ "realpath-missing",
315
+ "rename-overwrite",
316
+ "render-help",
317
+ "resolve-link-target",
318
+ "root-link-target",
319
+ "run-groups",
320
+ "safe-execa",
321
+ "safe-promise-defer",
322
+ "symlink-dir",
323
+ "tar@7.5.10",
324
+ "which-pm",
325
+ "which-pm-runs",
326
+ "write-ini-file",
327
+ "write-json5-file",
328
+ "write-yaml-file",
329
+ "tmp@0.2.6",
330
+ "http-proxy-middleware@3.0.7",
331
+ "get-pnpm@0.0.2 || 0.0.3"
332
+ ],
281
333
  "minimumReleaseAgeIgnoreMissingTime": true,
334
+ "minimumReleaseAgeStrict": true,
282
335
  "nodeLinker": "hoisted",
283
336
  "optional": true,
284
337
  "patchedDependencies": {
@@ -288,6 +341,16 @@
288
341
  "peersSuffixMaxLength": 1000,
289
342
  "preferWorkspacePackages": false,
290
343
  "production": true,
291
- "publicHoistPattern": []
344
+ "publicHoistPattern": [],
345
+ "trustPolicy": "no-downgrade",
346
+ "trustPolicyExclude": [
347
+ "@pnpm/*",
348
+ "@yarnpkg/libzip@3.2.2",
349
+ "pnpm",
350
+ "rxjs@7.8.2",
351
+ "tinyexec@1.2.2",
352
+ "undici-types@6.21.0"
353
+ ],
354
+ "trustPolicyIgnoreAfter": 10080
292
355
  }
293
356
  }
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "./dist/node_modules/node-gyp/gyp/gyp"
10
10
  ]
11
11
  },
12
- "version": "12.0.0-rc.6",
12
+ "version": "12.0.0-rc.7",
13
13
  "description": "Fast, disk space efficient package manager",
14
14
  "keywords": [
15
15
  "pnpm",
@@ -46,14 +46,14 @@
46
46
  "THIRD-PARTY-NOTICES.md"
47
47
  ],
48
48
  "optionalDependencies": {
49
- "@pnpm/exe.win32-x64": "12.0.0-rc.6",
50
- "@pnpm/exe.win32-arm64": "12.0.0-rc.6",
51
- "@pnpm/exe.darwin-x64": "12.0.0-rc.6",
52
- "@pnpm/exe.darwin-arm64": "12.0.0-rc.6",
53
- "@pnpm/exe.linux-x64": "12.0.0-rc.6",
54
- "@pnpm/exe.linux-arm64": "12.0.0-rc.6",
55
- "@pnpm/exe.linux-x64-musl": "12.0.0-rc.6",
56
- "@pnpm/exe.linux-arm64-musl": "12.0.0-rc.6"
49
+ "@pnpm/exe.win32-x64": "12.0.0-rc.7",
50
+ "@pnpm/exe.win32-arm64": "12.0.0-rc.7",
51
+ "@pnpm/exe.darwin-x64": "12.0.0-rc.7",
52
+ "@pnpm/exe.darwin-arm64": "12.0.0-rc.7",
53
+ "@pnpm/exe.linux-x64": "12.0.0-rc.7",
54
+ "@pnpm/exe.linux-arm64": "12.0.0-rc.7",
55
+ "@pnpm/exe.linux-x64-musl": "12.0.0-rc.7",
56
+ "@pnpm/exe.linux-arm64-musl": "12.0.0-rc.7"
57
57
  },
58
58
  "scripts": {
59
59
  "preinstall": "node install.js",