Commit Graph

2682 Commits

Author SHA1 Message Date
Victor Sumner
9f5c0e391f fix(config): respect explicit enableGlobalVirtualStore in CI environments (#10836)
Previously, `ci: true` (auto-detected or configured) unconditionally
set `enableGlobalVirtualStore` to `false`, even when the user had
explicitly enabled it in `pnpm-workspace.yaml` or via CLI. This forced
users to add `ci: false` as a workaround in their workspace config
whenever they wanted GVS in CI-like environments (Nix builds, CI systems
with persistent caches, Docker multistage builds).

Now, the CI override only applies when `enableGlobalVirtualStore` was
not explicitly set (i.e., is `null` or `undefined`). This preserves the
default behavior for ephemeral CI while respecting explicit user
configuration.

Also removes the `ci: false` workarounds from existing tests that
were documenting this limitation.

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-03-03 01:59:57 +01:00
Zoltan Kochan
2efb5d2919 feat: add pnpm runtime set command and deprecate pnpm env use (#10671)
* feat: add `pnpm runtime set` command and deprecate `pnpm env use`

Add a new `pnpm runtime set <name> <version> [-g]` command (alias: `rt`)
in a new `@pnpm/runtime.commands` package. It delegates to
`pnpm add <name>@runtime:<version>` supporting node, deno, and bun.

`pnpm env use` now prints a deprecation warning pointing users to the
new command.

* fix: address PR review feedback for runtime command

- Use opts.dir as cwd when --global is not passed (instead of always
  using pnpmHomeDir)
- Only pass --global-bin-dir when in global mode
- Keep deprecated env command in help output for discoverability
- Add Jest tests for the runtime command (7 tests)
2026-03-01 18:14:57 +01:00
Zoltan Kochan
543c7e4bae feat: use global virtual store for global packages and dlx (#10694)
* feat: use global virtual store for global packages and dlx

* fix(config): remove unnecessary virtualStoreDir override for global installs

When the global virtual store is disabled, the default `node_modules/.pnpm`
path works fine — no need to explicitly override it to `.pnpm`.
2026-03-01 18:03:04 +01:00
Zoltan Kochan
9587dac9c1 feat!: change default values of optimisticRepeatInstall and verifyDepsBeforeRun (#10822) 2026-03-01 17:48:13 +01:00
Zoltan Kochan
de561a55fa fix: prefer .pnpmfile.mjs by default (#10683)
* fix: prefer .pnpmfile.mjs by default

* fix: handle ERR_MODULE_NOT_FOUND for missing optional .pnpmfile.mjs

Node's dynamic import() throws ERR_MODULE_NOT_FOUND (not MODULE_NOT_FOUND
like require()) when a file doesn't exist. This caused a hard error when
tryLoadDefaultPnpmfile was enabled and .pnpmfile.mjs was absent.

* fix: load only .pnpmfile.mjs when it exists, not both .mjs and .cjs

When both .pnpmfile.mjs and .pnpmfile.cjs exist, only the .mjs file
is now loaded. Previously both were loaded and their hooks combined.
Also adds .mjs support for config dependency plugins.
2026-03-01 17:00:33 +01:00
Conny Brunnkvist
e1ea7799ea feat(cli): add -F short alias for --filter (#10821) 2026-03-01 15:51:34 +01:00
Zoltan Kochan
fd511e4676 feat: isolated global packages (#10697)
**TLDR:** Global packages in pnpm v10 are annoying and slow because they all are installed to a single global package. Instead, we will now use a system that is similar to the one used by "pnpm dlx" (aka "pnpx").

Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own `package.json`, `node_modules`, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts or version resolution shifts.

## Changes

- Add `@pnpm/global-packages` shared utilities package for scanning, hashing, and managing isolated global installs
- `pnpm add -g` creates isolated installs in `{pnpmHomeDir}/global/v11/{hash}/`
- `pnpm remove -g` removes the entire installation group containing the package
- `pnpm update -g` re-installs into new isolated directories and swaps symlinks
- `pnpm list -g` scans isolated directories to show installed global packages
- `pnpm outdated -g` checks each isolated installation for outdated dependencies
- `pnpm store prune` cleans up orphaned global installation directories

## Breaking changes

- `pnpm install -g` (no args) is no longer supported — use `pnpm add -g <pkg>`
- `pnpm link <pkg-name>` no longer resolves packages from the global store — only relative or absolute paths are accepted
- `pnpm link --global` is removed — use `pnpm add -g .` to register a local package's bins globally
2026-03-01 15:49:18 +01:00
Zoltan Kochan
030001035b feat: add pnpm clean command for safe node_modules/lockfile removal (#10708)
* feat: add `pnpm clean` command for safe node_modules removal

Adds a new `pnpm clean` command that safely removes node_modules contents
from all workspace projects. Uses Node.js fs.rm() which correctly handles
NTFS junctions on Windows without following them into their targets,
preventing catastrophic data loss. Preserves non-pnpm hidden files
(e.g. .cache) and lockfiles by default; use --lockfile/-l to also
remove pnpm-lock.yaml files. Also cleans custom virtual-store-dir
when configured inside the project root.

Closes #10707

* fix: use is-subdir package instead of custom implementation, check existence before printing

- Replace custom isSubdir function with the existing is-subdir package
- Only print "Removing" and remove lockfile/virtualStoreDir when they exist
- Rethrow non-ENOENT errors instead of swallowing them

* refactor: use path-exists package, handle TOCTOU race in removeModulesDirContents

- Replace manual fs.access + try/catch with pathExists for cleaner existence checks
- Add ENOENT handling to removeModulesDirContents readdir to handle the race
  where the directory is removed between hasContentsToRemove and readdir

* refactor: use opts object with .bind for cleanProjectDir, rename to removeLockfile
2026-02-28 22:53:56 +01:00
Ishan Gupta
f8367e88d2 fix(dlx): print help message when no arguments are provided (#10690)
* fix(dlx): print help message on calling pnpm dlx without arguments

Running `pnpm dlx` with no arguments would crash Node.js with a
TypeError as it attempted to call `.indexOf()` on an undefined variable.
This commit adds a guard clause and displays the help message instead
and exits gracefully.

Fixes #10633

* refactor: dlx

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-02-28 02:02:53 +01:00
roysandrew
143ca78d09 fix(npm-resolver): respect version constraints when falling back to workspace packages (#10704)
* fix(npm-resolver): respect version constraints when falling back to workspace packages

When link-workspace-packages=true, the fallback resolution paths (registry 404
and no matching registry version) pass update: Boolean(opts.update) to
tryResolveFromWorkspacePackages. On fresh installs without a lockfile entry,
opts.update is 'compatible' (truthy), which overrides the version spec to '*'
and matches any workspace package regardless of version.

Change both fallback call sites to pass update: false so version constraints
are always respected for non-workspace-protocol dependencies. The workspace:
protocol path returns before these blocks and correctly continues to use
opts.update.

Close #10173

* test: clarify npm-resolver test names for workspace version mismatch scenarios

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-02-28 01:52:38 +01:00
Zoltan Kochan
521e4a6ec9 fix: use headless install for injected self-referencing file: dependencies (#10714)
When a package has an injected self-referencing dependency (e.g.
"pkg": "file:" with dependenciesMeta injected: true), the lockfile
resolves it as "link:". The linkedPackagesAreUpToDate() function
incorrectly reported these projects as not up-to-date because
refToRelative() returns null for link: refs, causing pnpm to skip
the fast headless install path and do full resolution instead.
2026-02-28 01:39:42 +01:00
Umesh More
cb49a64af7 fix(patch): prevent git config path errors in patch-commit (#10640)
* fix(patch): prevent git config path errors in patch-commit

Replace HOME='' with GIT_CONFIG_GLOBAL to bypass user config
without breaking home directory resolution in restricted environments.

Fixes #6537

* fix(patch): prevent git config path errors in patch-commit

Use GIT_CONFIG_NOSYSTEM and GIT_CONFIG_GLOBAL to bypass git config
without breaking HOME path resolution in restricted environments.

Fixes #6537
2026-02-28 01:37:37 +01:00
Zoltan Kochan
05158d2cde fix: comparison of hoistPattern values (#10713) 2026-02-27 23:51:58 +01:00
Victor Sumner
97f049fb6a fix: skip re-importing packages when global virtual store is warm (#10709)
* fix: skip re-importing packages when global virtual store is warm

When node_modules is deleted but the global virtual store directories
survive, pnpm previously re-fetched every package because the skip
logic required currentLockfile to be present. Add a fast-path that
checks pathExists(dir) for GVS directories even when currentLockfile
is missing, since the GVS directory hash encodes engine, integrity,
and full dependency subgraph.

* fix: remove includeUnchangedDeps guard from GVS fast-path

The includeUnchangedDeps flag is true whenever currentHoistPattern
differs from the desired hoistPattern. After deleting node_modules,
currentHoistPattern is always undefined (read from .modules.yaml),
so the flag is always true when hoisting is configured — defeating
the optimization in the exact scenario it targets.

The guard is unnecessary because the fast-path only skips fetch/import
(fetchResponse = {}), not graph inclusion. The package is still added
to the graph with children populated, so hoisting recalculation works.

* perf: add GVS warm reinstall benchmark scenario

Adds benchmark 6: frozen lockfile reinstall with a warm global virtual
store after deleting node_modules. This measures the reattach fast-path
where all packages are skipped (no fetch/import) because their GVS
hash directories already exist.

* fix: use proper types in fetchPackage spy to pass tsgo strict checks
2026-02-27 22:51:08 +01:00
Ishan Gupta
d3a0765bea fix(dependencies-hierarchy): handle undefined pkgSnapshot in pnpm why -r (#10705)
* fix(dependencies-hierarchy): handle undefined pkgSnapshot in pnpm why -r

Running pnpm why -r crashes with TypeError due to undefined pkgSnapshot during
invokation of pkgSnapshotToResolution.

This commit wraps resolution and integrity steps with if (pkgSnapshot).
Also, added unit test for the same.

close #10700

* fix: handle undefined pkgSnapshot in pnpm why -r

* Apply suggestions from code review

#10700

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-27 17:28:55 +01:00
Zoltan Kochan
1ab0f7bb2a fix: run @pnpm/exe setup logic in-process to fix version switching without Node.js (#10696)
When pnpm is installed as a standalone executable in environments without
a system Node.js (e.g. Docker containers), the `@pnpm/exe` preinstall
script (`node setup.js`) fails because `node` is not on PATH. This broke
version switching via the `packageManager` field in package.json since
v10.30.2, which changed `getCurrentPackageName()` to return `@pnpm/exe`
instead of platform-specific package names like `@pnpm/linux-x64`.

Install with `--ignore-scripts` and link the platform-specific binary
in-process instead. The setup logic is inlined because setup.js can't
be loaded at runtime: `require()` fails on ESM (pnpm v11+) and
`import()` is intercepted by pkg's virtual filesystem in standalone
executables.

Closes #10687
2026-02-26 10:46:43 +01:00
Zoltan Kochan
dcd16c7b36 fix: pnpm why -r --parseable (#10595)
close #8100
2026-02-26 02:00:45 +01:00
sadan4
a2591e8cda fix(shell-completion): give correct suggestions when command line ends with a space (#10607)
* fix(shell-completion): give correct suggestions when command line ends with a space

fixes an issue where if you tried to complete any part of any subcommand
with a space before <TAB> (eg: `pnpm run <TAB>`, `pnpm rm react <TAB>`),
pnpm would give you suggestions for the root command, as if you had
typed `pnpm <TAB>`

close #7964
close #5426

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-02-25 11:37:48 +01:00
thilllon
2e8816e83b feat(approve-builds): add --all flag to skip interactive prompts (#10619)
Allow approving all pending build dependencies at once without
interactive selection, useful for CI/CD pipelines and project
bootstrapping scenarios where interactive prompts are not feasible.

close #10136
2026-02-25 11:36:49 +01:00
Varun Chawla
e73da5e27b fix(lockfile): respect lockfile-include-tarball-url=false for non-standard URLs (#10621)
When lockfile-include-tarball-url is explicitly set to false, tarball URLs
are now always excluded from the lockfile. Previously, packages hosted under
non-standard tarball URLs would still have their tarball field written to the
lockfile even when the setting was false, causing flaky and inconsistent
behavior across environments.

The fix makes the option tri-state internally:
- true: always include tarball URLs
- false: never include tarball URLs
- undefined (not set): use the existing heuristic that includes tarball URLs
  only for packages with non-standard registry URLs

close #6667
2026-02-25 11:03:32 +01:00
Allan Kimmer Jensen
f92ac24c1b feat(sbom): add pnpm sbom command (#10592)
* feat(sbom): add `pnpm sbom` command (#9088)

new command that generates SBOMs from the lockfile + store metadata.
supports CycloneDX 1.6 JSON and SPDX 2.3 JSON via `--sbom-format`.

two new packages following the existing `pnpm licenses` architecture:
- `@pnpm/sbom` — core library (lockfile walking, store reading, serializers)
- `@pnpm/plugin-commands-sbom` — CLI plugin wiring

uses the lockfile walker for dependency traversal and reads package.json
from the CAFS store for license/author/description metadata. `--lockfile-only`
skips the store entirely for faster CI runs where metadata isn't needed.

validated against official CycloneDX 1.6 and SPDX 2.3 JSON schemas.

* chore: add sbom-related words to cspell dictionary

* fix(sbom): address CycloneDX review feedback and bump to 1.7

Implements all 5 items from the CycloneDX maintainer review:
split scoped names into group/name, move hashes to
externalReferences distribution, use license.id for known SPDX
identifiers, switch to modern tools.components structure with
pnpm version, and bump specVersion to 1.7.

Also adds spdx-license-ids for proper license classification and
improves SPDX serializer test coverage.

* fix(sbom): fix CI bundle failure for spdx-license-ids

createRequire doesn't work in the esbuild bundle since it's a runtime
resolve, switched back to regular import which esbuild can inline.

* fix(sbom): use tarball URL for distribution externalReferences

Use actual tarball download URL instead of PURL for CycloneDX
distribution externalReferences, per review feedback.

* feat(sbom): add CycloneDX metadata and improve SBOM quality scores

adds $schema, timestamp, lifecycles (build/pre-build) to CycloneDX output
to match what npm does. also enriches both CycloneDX and SPDX with
metadata.authors, metadata.supplier, component supplier from author,
vcs externalReferences from repository, and root component details
(purl, license, description, author, vcs). SPDX now uses tarball URL
for downloadLocation instead of NOASSERTION.

renames CycloneDxToolInfo to CycloneDxOptions, passes lockfileOnly
through to the serializer for lifecycle phase selection. adds store-dir
to accepted CLI options.

* fix(sbom): address CycloneDX review feedback round 2

switches license classification from spdx-license-ids to
@cyclonedx/cyclonedx-library (SPDX.isSupportedSpdxId) for accurate
CycloneDX license ID validation per jkowalleck's feedback.

removes hardcoded metadata.authors and metadata.supplier — these are
not appropriate for a tool to set. adds --sbom-authors and
--sbom-supplier CLI flags so the SBOM consumer (e.g. ACME Corp) can
declare who they are.

removes supplier from components — supplier is the registry/distributor,
not the package author. also fixes distribution externalReference to
only emit when a real tarball URL exists, no PURL fallback.

* fix(sbom): use sub-path import for CycloneDX library to fix bundle

top-level import from @cyclonedx/cyclonedx-library drags in
validation/serialize layers with optional deps (ajv-formats, libxmljs2,
xmlbuilder2) that esbuild can't resolve during pnpm CLI bundling.

switch to @cyclonedx/cyclonedx-library/SPDX which only pulls in the
SPDX module we actually use — pure JS, no optional deps.

* chore: update manifests

* refactor: extract shared store-reading logic into @pnpm/store.pkg-finder

Both @pnpm/license-scanner and @pnpm/sbom independently implemented
nearly identical logic to read a package's file index from the
content-addressable store. This extracts that into a new shared package
that returns a uniform Map<string, string> (filename → absolute path),
simplifying both consumers.

Close #9088

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-02-25 08:45:21 +01:00
Jake Bailey
ccec8e7d87 fix(config): respect lockfile: false setting from pnpm-workspace.yaml (#10672)
* fix(config): respect lockfile: false setting from pnpm-workspace.yaml

* fix(config): derive lockfile settings after all config sources are applied

* fix(config): use lockfile instead of useLockfile in integration tests
2026-02-23 16:22:29 +01:00
Zoltan Kochan
cb228c900c fix(link-bins): stop prepending redundant paths to NODE_PATH in command shims (#10673)
Fixed "input line too long" error on Windows when running lifecycle scripts with the global virtual store enabled. The `NODE_PATH` in command shims no longer includes all paths from `Module._nodeModulePaths()`. Instead, it includes only the package's bundled dependencies directory (e.g., `.pnpm/pkg@version/node_modules/pkg/node_modules`), the package's sibling dependencies directory (e.g., `.pnpm/pkg@version/node_modules`), and the hoisted `node_modules` directory. These paths are needed so that tools like `import-local` (used by jest, eslint, etc.) which resolve from CWD can find the correct dependency versions.
2026-02-23 04:19:32 +01:00
Zoltan Kochan
54c4fc4fb4 fix: respect peer dep range in hoistPeers when preferred versions exist (#10655)
* fix: respect peer dep range in hoistPeers when preferred versions exist

Previously, hoistPeers used semver.maxSatisfying(versions, '*') which
picked the highest preferred version from the lockfile regardless of the
peer dep range. This caused overrides that narrow a peer dep range to be
ignored when a stale version existed in the lockfile.

Now hoistPeers first tries semver.maxSatisfying(versions, range) to find
a preferred version that satisfies the actual peer dep range. If none
satisfies it and autoInstallPeers is enabled, it falls back to the range
itself so pnpm resolves a matching version from the registry.

* fix: only fall back to exact-version range for overrides, handle workspace: protocol

- When no preferred version satisfies the peer dep range, only use the
  range directly if it is an exact version (e.g. "4.3.0" from an override).
  For semver ranges (e.g. "1", "^2.0.0"), fall back to the old behavior
  of picking the highest preferred version for deduplication.
- Guard against workspace: protocol ranges that would cause
  semver.maxSatisfying to throw.
- Add unit tests for hoisting deduplication and workspace: ranges.

* fix: only apply range-constrained peer selection for exact versions

The previous approach used semver.maxSatisfying(versions, range) for all
peer dep ranges, which broke aliased-dependency deduplication — e.g. when
three aliases of @pnpm.e2e/peer-c existed at 1.0.0, 1.0.1, and 2.0.0,
range ^1.0.0 would pick 1.0.1 instead of 2.0.0.

Now the range-aware logic only activates when the range is an exact
version (semver.valid), which is the override case (e.g. "4.3.0").
Regular semver ranges fall back to picking the highest preferred version.
2026-02-22 22:04:35 +01:00
Zoltan Kochan
23eb4a6141 refactor(env): unify node version specifier parsing into parseNodeSpecifier in node.resolver (#10668)
* refactor(env): unify node version specifier parsing into parseNodeSpecifier in node.resolver

Move parseNodeSpecifier from @pnpm/plugin-commands-env to @pnpm/node.resolver and
replace the simpler parseEnvSpecifier with an enhanced version that supports all
Node.js version specifier formats: standalone release channels (nightly, rc, test,
v8-canary, release), well-known aliases (lts, latest), LTS codenames (argon, iron),
semver ranges (18, ^18), and channel/version combos (rc/18, nightly/latest).

* fix(env): address parseNodeSpecifier review feedback

- Remove overly strict release/X.Y.Z-only validation; release/latest,
  release/lts, and release/<range> are now accepted
- Validate unknown release channels (e.g. foo/18) with a clear error
  instead of letting them fall through to a confusing network failure
- Add test cases for release/latest, release/lts, and release/18
2026-02-22 14:34:02 +01:00
Zoltan Kochan
50fbecae7d refactor(env): pnpm env use now delegates to pnpm add --global (#10666)
This PR overhauls `pnpm env` use to route through pnpm's own install machinery instead of maintaining a parallel code path with manual symlink/shim/hardlink logic.

```
pnpm env use -g <version>
```

now runs:

```
pnpm add --global node@runtime:<version>
```

via `@pnpm/exec.pnpm-cli-runner`. All manual symlink, hardlink, and cmd-shim code in `envUse.ts` is gone (~1000 lines removed across the package).

### Changes

**npm and npx shims on all platforms**

Added `getNodeBinsForCurrentOS(platform)` to `@pnpm/constants`, returning a `Record<string, string>` with the correct relative paths for `node`, `npm`, and `npx` inside a Node.js distribution. `BinaryResolution.bin` is widened from `string` to `string | Record<string, string>` in `@pnpm/resolver-base` and `@pnpm/lockfile.types`, so the node resolver can set all three entries and pnpm's bin-linker creates shims for each automatically.

**Windows npm/npx fix**

`addFilesFromDir` was skipping root-level `node_modules/` (to avoid storing a package's own dependencies), which stripped the bundled `npm` from Node.js Windows zip archives. Added an `includeNodeModules` option and enabled it from the binary fetcher so Windows distributions keep their full contents.

**Removed subcommands**

`pnpm env add` and `pnpm env remove` are removed. `pnpm env use` handles both installing and activating a version. `pnpm env list` now always lists remote versions (the `--remote` flag is no longer required, though it is kept for backwards compatibility).

**musl support**

On Alpine Linux and other musl-based systems, the musl variant of Node.js is automatically downloaded from [unofficial-builds.nodejs.org](https://unofficial-builds.nodejs.org).
2026-02-22 12:06:34 +01:00
Zoltan Kochan
9065f491f0 feat: add musl support to node runtime (#10664)
The lockfile now includes musl Linux builds (sourced from
unofficial-builds.nodejs.org) alongside the standard glibc variants,
so that `node@runtime:` works out of the box on Alpine Linux and other
musl-based distributions.

`env use` can download node.js artifacts for systems that use musl.
2026-02-21 21:29:05 +01:00
Zoltan Kochan
03c502c1a0 fix: detect overrides and other lockfile-affecting setting changes in optimisticRepeatInstall (#10654)
* fix: detect overrides and other lockfile-affecting setting changes in optimisticRepeatInstall

When optimisticRepeatInstall was enabled, changing overrides,
packageExtensions, ignoredOptionalDependencies, patchedDependencies,
or peersSuffixMaxLength would not trigger a reinstall because these
settings were not tracked in the workspace state file.

* refactor: extract WORKSPACE_STATE_SETTING_KEYS to prevent type/runtime drift

The settings key list in createWorkspaceState's pick() call must stay
in sync with the WorkspaceStateSettings type. Extract a shared const
array so both the type and runtime pick are derived from a single
source, preventing the class of bug fixed in the previous commit.
2026-02-20 14:00:25 +01:00
mitchell amihod
a969839845 fix(audit): help text for --ignore-registry-errors was missing a "not" (#10656)
Signed-off-by: meeech <4623+meeech@users.noreply.github.com>
2026-02-20 01:21:18 +01:00
Carey Janecka
315cae83f8 fix(audit): fallback to quick audit endpoint (#10652)
* fix(audit): fallback to quick audit endpoint

Fallback to /audits/quick when /audits fails with non-200, avoiding 5xx hard failures.

Close #10649

* refactor(audit): reuse request options for fallback

Share request options between primary and quick audit endpoints. Use POST for consistency.

* fix(audit): use quick audit endpoint as primary, full as fallback

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-02-20 00:53:01 +01:00
Zoltan Kochan
d0c6f59285 docs: fix changeset 2026-02-17 12:09:50 +01:00
Zoltan Kochan
56a59df674 perf: persist bundled manifest in store index to avoid reading package.json from CAFS (#10473)
close #10461
2026-02-17 12:03:08 +01:00
Zoltan Kochan
7116f35027 feat: add nameFormatter option to buildDependentsTree for custom display names (#10629)
Allow consumers (e.g. Bit CLI) to provide a nameFormatter callback that
reads the package manifest and returns a custom display name. The resolved
displayName is carried through the DependentsTree/DependentNode data model
and used by all render functions (tree, JSON, parseable).
2026-02-15 22:25:41 +01:00
Brandon Cheng
0e9c559068 fix: remove misleading maxAge argument to pMemoize (#10620) 2026-02-15 22:07:29 +01:00
Zoltan Kochan
7d5ada0701 feat: reverse pnpm why tree and improve list/why output (#10615)
- **`pnpm why` now shows a reverse dependency tree.** The searched package appears at the root with its dependants as branches, walking back to workspace roots. This replaces the previous forward-tree output which was noisy and hard to read for deeply nested dependencies.
- **Replaced `archy` with a new `@pnpm/text.tree-renderer` package** that renders trees using box-drawing characters (├──, └──, │) and supports grouped sections, dim connectors, and deduplication markers.
- **Show peer dependency hash suffixes** in `pnpm list` and `pnpm why` output to distinguish between different peer-dep variants of the same package.
- **Improved `pnpm list` visual output:** bold importer nodes, dimmed workspace paths, dependency grouping, package count summary, and deterministic sort order.
- **Added `--long` support to `pnpm why`** and the ability to read package manifests from the CAS store.
- **Deduplicated shared code** between `list` and `why` commands into a common module, and reused `getPkgInfo` in the why tree builder.
2026-02-15 14:38:43 +01:00
Zoltan Kochan
472d3af93d perf: share dependency graph and materialization cache across importers in list/why (#10596) 2026-02-13 21:13:02 +01:00
Ryo Matsukawa
fa5a5c6c76 fix: dynamically calculate column widths in interactive update table (#10585)
* fix: dynamically calculate column widths in interactive update table

* test: implement copilot suggestions

* style: change order of functions

close #10316
2026-02-13 07:13:29 +01:00
Khải
cc7c0d22df refactor!: replace npm publish with libnpmpublish (#10591)
* chore(deps): add `libnpmpublish` to catalog

* chore(deps): install `libnpmpublish`

* feat: publishableManifest (wip)

* feat: publishableManifest (wip)

* chore(cspell): libnpmpublish

* test: fix

* feat: validate field and version

* chore: @npm/types

* chore: todo

* refactor: reorganize

* feat: transformRequiredFields

* chore(deps): patch `libnpmpublish`

* fix: `BaseManifest.config`

* fix: eslint

* chore(git): revert a patch that doesn't work

This reverts commit 45f2c6a6c2.

We will use type casting

* feat: `engines.runtime`

* feat: normalize bin

* fix: `bin === ''`

* test: fix

* refactor: inference friendly

* feat: `peerDependenciesMeta`

* refactor: group into a directory

* refactor: use `ramda.pipe`

* refactor: less intrusive type assertion

* feat!: returning `ExportedManifest`

* refactor: remove unnecessary file

* docs: add a todo

* refactor: getNetworkConfigs (#10458)

Some tests are added as a bonus

* feat: `publishPackedPkg` (wip)

* feat: replace `\t` with 4 spaces

* fix: newline

* fix: newline

* refactor: extract `FailedToPublishError`

* test: FailedToPublishError

* feat: registryConfigKeys

* feat: `publishPackedPkg` (wip)

* feat(config/getNetworkConfigs): load auth info

* feat(config/getNetworkConfigs): load auth info (#10491)

* feat: `publishPackedPkg` (wip)

* refactor: extract a `static` function

* fix: inheritance, override, and merge

* feat: `executeTokenHelper`

* fix: use the visible `globalWarn`

* feat: add options

* feat: add more options

* docs: more links

* fix: private packages

* fix: --dry-run

* feat: log more things

* fix: name

* fix: tag

* refactor: remove extraneous `assertPublicPackage`

* feat: use `publishPackedPkg` for directories

* refactor: require only necessary fields

* refactor: extractManifestFromPacked

* fix: extractManifestFromPacked

* test: extractManifestFromPacked

* feat: isTarballPath

* feat: use `publishPackedPkg` for tarballs

* style: add an empty line for clarity

* refactor: remove unnecessary works

* feat: --otp

* feat: PNPM_CONFIG_OTP

* feat: oidc

* test: fix name collision

* fix: eslint

* test: disable a false test

* feat: set `provenance`

* docs(todo): auto provenance

* refactor: run oidc in `createPublishOptions`

* fix: correct auth keys for `libnpmpublish`

* docs: changeset

* fix: incorrect `password` field

* fix: typo, grammar

* chore(git): resolve merge conflict ahead of time

In preparation for https://github.com/pnpm/pnpm/pull/10385

* fix: field name

* fix(config): decoding `_password`

* fix: edge case of partial `cert`/`key`

* fix: ensure `registry` always match its config key

* fix: `_password`

* test: correct a name

* test: more specific assertions

* fix: grammar

* docs(changeset): fix grammar

* docs: fix grammar

* fix: clean up after failure

* test: fix windows

* feat(provenance): auto detect

* refactor: consistent name

* fix: correct error names

* refactor: extract the `provenance` code

* feat: show code and body of an error

* refactor: use `encodeURIComponent`

* refactor: rename a type

* refactor: use the try-catch model

* refactor: move `normalizeBinObject`

* refactor: split `oidc` into `idToken` and `authToken`

* refactor: run `next` on `stream`'s `'end'`

* fix: use the correct encoding

* feat: guard against weird names

* test: `transform/engines`

Closes https://github.com/pnpm/pnpm/pull/10599

* test: `transformPeerDependenciesMeta`

Closes https://github.com/pnpm/pnpm/pull/10600

* refactor: dependency inject the `Date` too

* refactor: export an interface

* test: oidc

Closes https://github.com/pnpm/pnpm/pull/10598

* refactor: re-arrange imports

* refactor: remove unnecessary type casts

* refactor: improve test
2026-02-12 21:10:54 +01:00
Brandon Cheng
5bf7768ca4 feat: skip confirm modules purge prompt if --yes is passed (#10383)
* feat: add --yes command line option

* feat: skip confirm modules purge prompt if --yes is passed

* refactor: factor out `ExecPnpmSyncOpts`

* test: add end-to-end test for --yes flag
2026-02-11 02:39:23 +01:00
Ryo Matsukawa
fa5ff08473 fix(dlx): respect minimumReleaseAgeExclude (#10572)
close #10338
2026-02-11 02:32:54 +01:00
Brandon Cheng
4c6c26a7e8 fix: disable global virtual store during pnpm deploy (#10577) 2026-02-11 02:19:43 +01:00
Karl Kaiser
1fd7370639 feat(workspace filtering): add support for filtering packages since last commit under git worktree (#10542)
support managing repo in git worktree for filtering for packages changed since last commit
2026-02-11 02:05:45 +01:00
Zoltan Kochan
a49b243573 fix: list command should not fail with an OOM error (#10586)
close #8731
2026-02-11 00:38:35 +01:00
Zoltan Kochan
cbb366a7aa fix: virtual store race condition (#10589) 2026-02-10 12:05:17 +01:00
Zoltan Kochan
861dd2a8a8 revert: fix(reviewing): fix memory error in pnpm why (#10582)
ref #7122
2026-02-09 15:05:09 +01:00
Zoltan Kochan
1b4df57a01 feat!: drop Node.js 20 and 21 support (#10569) 2026-02-08 19:16:24 +01:00
Zoltan Kochan
4720175176 fix: pnpm help should correctly show if pnpm is bundled with Node.js (#10563)
close #10561
2026-02-07 02:09:45 +01:00
btea
4158906724 feat: support auditLevel (#10554)
* feat: support `auditLevel`

* refactor: auditLevel

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-02-06 19:54:59 +01:00
Ryo Matsukawa
3c36e8d974 fix(audit): respect --audit-level in JSON output (#10547)
* fix(audit): respect --audit-level in JSON output

* refactor: audit

* docs: fix changeset

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-02-06 18:53:10 +01:00
Alessio Attilio
312226cbf0 fix: skip local file: protocol dependencies during pnpm fetch (#10514)
This fixes an issue where pnpm fetch would fail in Docker builds when
local directory dependencies (file: protocol) were not available.

The fix adds an ignoreLocalPackages option that is passed from the fetch
command to skip local dependencies during graph building, since pnpm
fetch only downloads packages from the registry and doesn't need local
packages that won't be available in Docker builds.

close #10460
2026-02-06 17:28:39 +01:00