Ana içeriğe geç

pnpm 12.2-12.3

· 8 dakikalık okuma
Zoltan Kochan
Lead maintainer of pnpm

pnpm 12.2 and 12.3 are largely a catch-up pair: a long list of things pnpm 11 did that the Rust CLI did not, put back. Catalogs learned the workspace: protocol, pnpm remove and pnpm update gained the supply-chain flags, every project-aware global command became a real executable, and hostname resolution went back to the system resolver on Linux and Windows. Large workspaces install noticeably faster.

Minor Changes

Catalogs can hold a workspace: range

A catalog entry may now be a workspace: range, so the version a workspace dependency is linked by is written in one place like every other version:

pnpm-workspace.yaml
catalog:
'@example/utils': workspace:^

A package.json referencing "@example/utils": "catalog:" links the workspace project, and both protocols are replaced on publish.

Supply-chain flags on remove and update

pnpm remove and pnpm update now take --trust-lockfile, --no-trust-lockfile, --trust-policy, --trust-policy-exclude, and --trust-policy-ignore-after, the same flags install and add take, so a policy can be relaxed or tightened for one run.

Removing a package rewrites the lockfile, so pnpm remove verifies the whole lockfile against the active policies rather than only the entries of the package it is removing. pnpm also honors --config.trust-lockfile=<value> and accepts the bare --trust-lockfile / --no-trust-lockfile spelling on the commands that previously read the setting from the config file alone.

Project-aware global commands are native executables

Every context-aware global command, node, deno, bun, and the shims pnpm shim add creates, is now a native executable on every platform. On Windows, <name>.exe replaces the .cmd and .ps1 pair.

The practical difference: no shell sits between you and the command, so an environment variable whose name is not a valid shell identifier survives the hop. Shims written by earlier pnpm 12 releases are migrated on the next global install or pnpm self-update.

Installs in large workspaces

Most of the work in these two releases went here, all of it under #14352:

  • Workspace patterns are probed concurrently and the discovered package.json files are read in parallel. Literal directories and trailing-star patterns take a shortcut.
  • pnpm-lock.yaml is parsed while the projects are being discovered, and the resolver no longer copies the whole lockfile before it starts.
  • The workspace dependency graph is built once per run instead of twice.
  • The check that decides whether the lockfile needs updating stopped comparing every project against every lockfile entry.
  • Each named workspace: dependency is resolved once and reused by every project that declares it, and link: dependencies re-anchor in lockfile-relative space.
  • Peer ranges are parsed once and cached, and the peer-dependency report at the end of a resolving install inspects only the projects resolution flagged (#14359).
  • Sorting and rendering the big lockfile sections happens in parallel.

Workspace patterns also follow pnpm 11's dot-directory rule again: a wildcard does not match a dot-prefixed directory, so packages/* and ** skip packages/.cache and .git. A pattern that names one explicitly still matches.

Networking

On both Linux and Windows, pnpm now resolves registry hostnames through the system resolver instead of its own DNS client.

On Windows the built-in client bound a UDP socket per lookup, which made Defender Firewall ask to allow pnpm.exe again after every pnpm self-update (#14405). On Linux an /etc/resolv.conf carrying an option the bundled resolver did not recognize, such as options no_tld_query, made pnpm ignore the configured nameservers and silently query Google's public DNS instead (#14469).

Fetch and tarball errors no longer print the secrets of the URL they name. Inline user:pass@ credentials and the query string or fragment of a signed URL are hidden, so a failed install cannot leak them into terminal scrollback or CI logs.

pnpm deploy without injected dependencies

pnpm deploy no longer requires injectWorkspacePackages. A linked workspace dependency is rewritten to a file: dependency in the dedicated deploy lockfile, and the peer dependencies it declares are bound to the deployed graph's own resolution.

Where a peer resolves to more than one version in that graph the binding is ambiguous, and choosing between the candidates is exactly what injecting the package would have decided, so the deploy still fails. It now fails with ERR_PNPM_DEPLOY_AMBIGUOUS_PEER, naming the package, the peer, and the competing versions, and suggesting an overrides entry, instead of refusing every non-injected workspace up front (#9386).

Other changes

  • pnpm add <local directory>, pnpm add <local tarball>, pnpm add file:<path> and pnpm add <tarball URL> work again. A specifier given without a <name>@ prefix is no longer read as a registry package name (#14437).
  • pnpm update --interactive renders its checklist the way pnpm 11 does. Group headings and column headers are separators the cursor skips, columns line up across groups, a toggles all and i inverts, and the confirmed selection is echoed (#14423).
  • pnpm run, pnpm exec, pnpm rebuild, the script shortcuts, and pnpm link, pnpm outdated, pnpm import, and the packing commands all load the pnpmfile, so updateConfig settings such as extraEnv and extraBinPaths reach the processes they spawn (#14433, #14377).
  • pnpm run "/pattern/" runs the matched scripts concurrently up to workspaceConcurrency, with prefixed output. Filtered and recursive run and exec no longer hang when a script reads from the terminal, so interactive prompts work again wherever pnpm never runs a second script alongside (#14397).
  • pnpm keeps the surrounding quotes out of .npmrc values, restoring authentication with registries configured as :_authToken="${TOKEN}" (#14427).
  • minimumReleaseAgeStrict defaults to true whenever minimumReleaseAge is explicitly configured, wherever it was set. The built-in 1440-minute default stays non-strict (#14409).
  • pnpm unpublish completes a registry's two-factor challenge instead of failing with ERR_PNPM_UNAUTHORIZED while logged in (#14464).
  • catalogMode and --save-catalog no longer move a local path, tarball, or workspace:<path> specifier into a catalog: such a specifier is resolved against the project that declares it, so one catalog entry cannot mean the same directory for every project (#14437).
  • pnpm config accepts -g, --location, and --json before its subcommand, and a global pnpm config skips project version switching, so registry authentication can be configured before pnpm downloads a project-pinned version (#14421, #14463).
  • Detached child processes survive on Windows, including when another program launches pnpm directly without a shell, as nr from @antfu/ni does (#14447).
  • Transient Windows file-lock errors are retried while linking dependencies with the isolated linker and while replacing hoisted packages (#14407, #14349).
  • globalDir and globalBinDir are honored wherever they are set, so pnpm add -g no longer fails after pnpm config set -g global-bin-dir (#14336).
  • Resolution works against registries whose version manifests carry _npmUser, dist.attestations, dist.unpackedSize, dist.fileCount, or peerDependenciesMeta in a shape npm does not use. Such a version was skipped as though it had never been published.
  • pnpm audit --fix works without a value and when another flag follows it, and --fix=override respects saveExact and savePrefix (#13261, #11523).

pnpr 0.1.0-alpha.10

A shared build artifact publication that cannot unregister itself no longer stops the registry reclaiming space or refusing further publications. A publication says at intervals that it is still working, and a registration that has gone quiet for an hour is written off. A publication whose bookkeeping write failed therefore stops holding back the collector that reclaims unreferenced blobs, returns the compatibility scopes it claimed, and stops counting toward the limit on publications in flight.

For the complete client changes, see the v12.2.0 and v12.3.0 release notes. The server changes are in the pnpr 0.1.0-alpha.10 release notes.