Commit Graph

78 Commits

Author SHA1 Message Date
Zoltan Kochan
6c480a4375 perf: replace node-fetch with undici (#10537)
Replace node-fetch with native undici for HTTP requests throughout pnpm.

Key changes:
- Replace node-fetch with undici's fetch() and dispatcher system
- Replace @pnpm/network.agent with a new dispatcher module in @pnpm/network.fetch
- Cache dispatchers via LRU cache keyed by connection parameters
- Handle proxies via undici ProxyAgent instead of http/https-proxy-agent
- Convert test mocking from nock to undici MockAgent where applicable
- Add minimatch@9 override to fix ESM incompatibility with brace-expansion
2026-03-29 12:44:00 +02:00
Alessio Attilio
d5be835735 feat: implement native recursive version command (#10879)
* feat: implement non-interactive version command

* fix: address review issues in version command

- Fix changeset package name to @pnpm/releasing.commands
- Use writeProjectManifest instead of writeJsonFile to preserve formatting
- Remove dead updateWorkspaceDependencies placeholder function
- Remove unused imports (path, ProjectManifest, writeJsonFile)
- Add expect.assertions(1) to prevent silent test pass on no-throw

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 11:51:54 +00:00
Zoltan Kochan
88ad21dff8 feat(publish): handle OTP and web-based authentication flows (#11019)
* feat(publish): handle OTP and web-based authentication flows (#10834)

Add OTP handling to `pnpm publish` with support for:
- Classic OTP prompt (manual code entry)
- Web-based authentication flow with QR code display and doneUrl polling
- `npm-auth-type: web` header to signal web auth support to the registry

Extract OTP logic into a dedicated `otp.ts` module with dependency
injection for testability. Consolidate shared context for OIDC and OTP.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Potential fix for pull request finding

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

* Potential fix for pull request finding

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

---------

Co-authored-by: KSXGitHub <11488886+KSXGitHub@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-03-18 23:11:17 +01:00
Jason Paulos
15549a9445 feat(audit): add fix update mode (#10341)
* feat(audit): add fix update mode

Add the ability to fix vulnerabilities by updating packages in the
lockfile instead of adding overrides.

* revert: remove audit-registry parameter

* fix: properly invoke audit command recursively on workspace

* fix: negative weight version priority & top-level pinned dep updating

* refactor: apply packageVulnerabilityAudit version preferences earlier

* chore: update changeset

* fix: vulnerability penalties are greater than direct dep weight

* test: use nock on mock registry directly

* fix: exit with 1 if it can't resolve all vulnerabilities to match npm

* fix: properly update workspace top-level pinned vulnerable dependencies

* fix: update lockfile

* fix: update vulnerabilities in catalogs

* chore: sync pnpm-lock.yaml with main
2026-03-12 21:42:49 +01:00
Zoltan Kochan
5a15a32d84 feat: use JSON for npm registry metadata cache instead of msgpack (#10886)
* feat: use JSON for npm registry metadata cache instead of msgpack

Switch the on-disk package metadata cache from msgpack (.mpk) to JSON (.json).
When metadata is not filtered, the raw JSON response from the registry is written
directly to disk with cachedAt injected, avoiding a parse-then-serialize round-trip.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: update lockfileOnly test to use .json metadata extension

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update resolving/npm-resolver/src/pickPackage.ts

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-06 17:39:54 +01:00
Zoltan Kochan
b7f0f21582 feat: use SQLite for storing package index in the content-addressable store (#10827)
## Summary

Replace individual `.mpk` (MessagePack) files under `$STORE/index/` with a single SQLite database at `$STORE/index.db` using Node.js 22's built-in `node:sqlite` module. This reduces filesystem syscall overhead and improves space efficiency for small metadata entries.

Closes #10826

## Design

### New package: `@pnpm/store.index`

A new `StoreIndex` class wraps a SQLite database with a simple key-value API (`get`, `set`, `delete`, `has`, `entries`). Data is serialized with msgpackr and stored as BLOBs. The table uses `WITHOUT ROWID` for compact storage.

Key design decisions:

- **WAL mode** enables concurrent reads from workers while the main process writes.
- **`busy_timeout=5000`** plus a retry loop with `Atomics.wait`-based `sleepSync` handles `SQLITE_BUSY` errors from concurrent access.
- **Performance PRAGMAs**: `synchronous=NORMAL`, `mmap_size=512MB`, `cache_size=32MB`, `temp_store=MEMORY`, `wal_autocheckpoint=10000`.
- **Write batching**: `queueWrites()` batches pre-packed entries from tarball extraction and flushes them in a single transaction on `process.nextTick`. `setRawMany()` writes immediate batches (e.g. from `addFilesFromDir`).
- **Lifecycle**: `close()` auto-flushes pending writes, runs `PRAGMA optimize`, and closes the DB. A `process.on('exit')` handler ensures cleanup even on unexpected exits.
- **`VACUUM` after `deleteMany`** (used by `pnpm store prune`) to reclaim disk space.

### Key format

Keys are `integrity\tpkgId` (tab-separated). Git-hosted packages use `pkgId\tbuilt` or `pkgId\tnot-built`.

### Shared StoreIndex instance

A single `StoreIndex` instance is threaded through the entire install lifecycle — from `createNewStoreController` through the fetcher chain, package requester, license scanner, SBOM collector, and dependencies hierarchy. This replaces the previous pattern of each component creating its own file-based index access.

### Worker architecture

Index writes are performed in the main process, not in worker threads. Workers send pre-packed `{ key, buffer }` pairs back to the main process via `postMessage`, where they are batched and flushed to SQLite. This avoids SQLite write contention between threads.

### SQLite ExperimentalWarning suppression

`node:sqlite` emits an `ExperimentalWarning` on first load. This is suppressed via a `process.emitWarning` override injected through esbuild's `banner` option, which runs on line 1 of both `dist/pnpm.mjs` and `dist/worker.js` — before any module that loads `node:sqlite`.

### No migration from `.mpk` files

Old `.mpk` index files are not migrated. Packages missing from the new SQLite index are re-fetched on demand (the same behavior as a fresh store).

## Changed packages

121 files changed across these areas:

- **`store/index/`** — New `@pnpm/store.index` package
- **`worker/`** — Write batching moved from worker module into `StoreIndex` class; workers send pre-packed buffers to main process
- **`store/package-store/`** — StoreIndex creation and lifecycle management
- **`store/cafs/`** — Removed `getFilePathInCafs` index-file utilities (no longer needed)
- **`store/pkg-finder/`** — Reads from StoreIndex instead of `.mpk` files
- **`store/plugin-commands-store/`** — `store status` uses StoreIndex
- **`store/plugin-commands-store-inspecting/`** — `cat-index` and `find-hash` use StoreIndex
- **`fetching/tarball-fetcher/`** — Threads StoreIndex through fetchers; git-hosted fetcher flushes before reading
- **`fetching/git-fetcher/`, `binary-fetcher/`, `pick-fetcher/`** — Accept StoreIndex parameter
- **`pkg-manager/`** — `client`, `core`, `headless`, `package-requester` thread StoreIndex
- **`reviewing/`** — `license-scanner`, `sbom`, `dependencies-hierarchy` accept StoreIndex
- **`cache/api/`** — Cache view uses StoreIndex
- **`pnpm/bundle.ts`** — esbuild banner for ExperimentalWarning suppression

## Test plan

- [x] `pnpm --filter @pnpm/store.index test` — Unit tests for StoreIndex CRUD and batching
- [x] `pnpm --filter @pnpm/package-store test` — Store controller lifecycle
- [x] `pnpm --filter @pnpm/package-requester test` — Package requester reads from SQLite index
- [x] `pnpm --filter @pnpm/tarball-fetcher test` — Tarball and git-hosted fetcher writes
- [x] `pnpm --filter @pnpm/headless test` — Headless install
- [x] `pnpm --filter @pnpm/core test` — Core install, side effects, patching
- [x] `pnpm --filter @pnpm/plugin-commands-rebuild test` — Rebuild reads from index
- [x] `pnpm --filter @pnpm/license-scanner test` — License scanning
- [x] e2e tests pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-03-06 12:59:04 +01:00
Zoltan Kochan
00e7787097 feat: allow global install to override bins owned by the new package (#10828)
* feat: allow global install to override bins owned by the new package

When a package name matches the bin name (e.g., `npm` package providing
`npm` bin), the new package gets priority and can override an existing
bin from another global package. The `npx` bin is also treated as owned
by the `npm` package via a hardcoded override map.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: run benchmarks on node.js 25

* feat: skip linking bins owned by existing global packages instead of failing

When installing a package globally (e.g. node) whose bins conflict with
an already-installed package that owns those bins (e.g. npm owns npm/npx),
the install now succeeds and skips linking the conflicting bins rather
than aborting with GLOBAL_BIN_CONFLICT.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: improve global bin conflict checks for aliased packages and multi-provider bins

Track all new bin providers (not just the last one) so ownership is
correctly resolved when multiple new packages provide the same bin.
Use manifest.name instead of the dependency alias when checking
existing package ownership, fixing incorrect decisions for aliased
installs. Use symlink-dir in tests for Windows compatibility and
remove a non-null assertion in link-bins.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use Set for conflicting bins lookup and fix error hint to use alias

Convert the conflicting bins collection from an array to a Set for O(1)
lookups. Use the dependency alias in the `pnpm remove -g` hint since
that is what the user originally installed with, showing both alias and
manifest name when they differ.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: remove changeset

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 15:42:04 +01:00
Zoltan Kochan
e91ced5c88 docs: update sponsors 2026-03-03 17:34:17 +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
Zoltan Kochan
37bc146342 chore: update cspell list 2026-02-28 02:19:07 +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
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
f54347e415 feat: replace pkg with Node.js SEA for standalone executables (#10661)
* feat: switch from pkg to Node.js SEA for creating standalone executables

Replace @yao-pkg/pkg with Node.js native Single Executable Applications
(--build-sea, Node.js 25.5+). The SEA binary embeds only pnpm.cjs (CJS
bootstrap), while pnpm.mjs and all assets live in a dist/ directory
shipped alongside the binary in platform-specific tarballs.

* refactor: move dist/ from platform packages to @pnpm/exe

The dist/ directory (pnpm.mjs, worker.js, templates, etc.) is identical
across all platforms, so ship it once in @pnpm/exe instead of duplicating
it in each platform package. Platform packages now only contain the
binary. The self-updater installs @pnpm/exe (not the platform package)
so it gets both dist/ and the binary via optionalDependencies.

* refactor: externalize @reflink/reflink in esbuild bundle

Make @reflink/reflink external in both the main and worker esbuild
bundles so the require() calls resolve at runtime from dist/node_modules
instead of being inlined. Add @reflink/reflink as a production dependency
of both pnpm (bundled into dist/node_modules by bundle-deps.ts) and
@pnpm/exe (installed by npm alongside the binary).

For GitHub release tarballs, only the target platform's reflink package
is kept. For @pnpm/exe npm publishing, all reflink platform packages
are stripped from dist/ since npm installs the right one automatically.

* chore: update cspell list

* test: update system-node-version tests for SEA detection

Mock @pnpm/cli-meta's detectIfCurrentPkgIsExecutable instead of
setting process.pkg, which is no longer used for SEA detection.

* test: improve cli-meta test coverage for SEA migration

Add tests for detectIfCurrentPkgIsExecutable() (non-SEA path) and
isExecutedByCorepack() which were previously untested. The SEA=true
path of detectIfCurrentPkgIsExecutable() cannot be unit tested since
node:sea is unavailable in an ESM test environment.

* refactor: move GitHub tarball assembly to copy-artifacts.ts

build-artifacts.ts (prepublishOnly of @pnpm/exe) now only builds the
SEA executables and prepares the exe npm dist/. The per-target dist/
assembly for GitHub release tarballs moves to copy-artifacts.ts, which
is the natural owner of that concern.

Other changes:
- Extract getReflinkKeepPackages/stripReflinkPackages to reflink-utils.ts
  with tests using node:test
- Move --force from top-level pnpm install in release.yml to the pnpm
  deploy in bundle-deps.ts, where it is actually needed to install all
  @reflink/reflink-* platform packages into dist/node_modules
- Change @pnpm/exe prepublishOnly to run pnpm's full prepublishOnly
  (compile + bundle-deps) so dist/node_modules is populated before
  build-artifacts.ts and copy-artifacts.ts read from pnpm/dist

* fix: copy dist/ alongside binary when running pnpm setup for SEA

When the pnpm CLI is a Node.js SEA binary, it requires a dist/ directory
adjacent to the executable at runtime (containing pnpm.mjs and bundled
node_modules). The copyCli function in plugin-commands-setup now copies
dist/ from alongside the current binary into the tools directory so that
the installed pnpm works correctly after `pnpm setup`.


* fix: avoid argument list too long when creating Windows zip archives


* fix: propagate errors in copy-artifacts script

Previously errors in createArtifactTarball were swallowed, causing the
script to exit 0 even when artifact creation failed. Now errors are
re-thrown with a descriptive message, and the top-level IIFE has a
.catch() handler that sets a non-zero exit code.


* refactor: remove reflink-utils.ts from @pnpm/exe

The stripReflinkPackages call in build-artifacts.ts stripped all platform
packages while keeping @reflink/reflink. Instead, just remove the entire
@reflink directory from dist/ — @pnpm/exe already declares @reflink/reflink
as a runtime dependency, so npm installs it (along with the right platform
package via optionalDependencies) automatically.

This eliminates reflink-utils.ts, its tests, and the code duplication with
copy-artifacts.ts.
2026-02-22 12:45:50 +01:00
Zoltan Kochan
7db6629485 fix: retry existence check in global virtual store race condition handler (#10636)
When 3+ threads/processes concurrently import the same package to the
global virtual store, a third party can rimraf the target between another
thread's failed rename and its existence check. Retry the check up to 4
times with 50ms delays to let the competing operation complete.
2026-02-17 14:46:43 +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
491813fc14 refactor: simplify dependenciesHierarchyForPackage by delegating to getTree (#10616)
Instead of manually iterating over top-level dependencies, calling
getPkgInfo/getTreeNodeChildId/getTree per dependency, and handling
dedup/search logic in parallel with materializeChildren, delegate
entirely to a single getTree call with the importer as root.

The returned PackageNode[] are then post-categorized into their
dependency fields (dependencies, devDependencies, optionalDependencies)
using a fieldMap built from the lockfile importer snapshot.

This eliminates the duplicated dedup/search handling between
dependenciesHierarchyForPackage and materializeChildren, and removes
the GetTreeResult wrapper type from getTree (now returns PackageNode[]
directly). The materializeChildren cache is now the sole mechanism for
cross-importer deduplication.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 22:08:36 +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
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
f2a6d0684b docs: update sponsors 2026-02-10 21:22:23 +01:00
Zoltan Kochan
cbb366a7aa fix: virtual store race condition (#10589) 2026-02-10 12:05:17 +01:00
Zoltan Kochan
57e99b6996 chore: update pnpm-lock.yaml (#10558)
---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-06 03:28:39 +01:00
Shunta Takemoto
0625e20442 feat: treat bare workspace: protocol as workspace:* (#10436)
* feat: treat bare `workspace:` protocol as `workspace:*`

* chore: add chageset

* test(exportable-manifest): add test for `workspace` with explicit versions

* test: add tests and update changesets

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-01-26 07:06:01 +01:00
Zoltan Kochan
e2e0a321b3 perf: optimize how the integrities of files in the CAFS are stored (#10504) 2026-01-24 21:41:11 +01:00
Zoltan Kochan
40b107efa7 perf: migrate internal cache and index files to MessagePack serialization (#10500) 2026-01-23 01:31:09 +01:00
Zoltan Kochan
ec7c5d7d1a feat: improve git URL detection to recognize plain HTTP/HTTPS URLs
Improve git URL detection to recognize plain HTTP/HTTPS URLs
ending in `.git` and prioritize git resolver over tarball resolver.

close #10468
2026-01-16 19:38:02 +01:00
Vedant Madane
29a3151b60 feat: show available workspace versions on mismatch (#10466) 2026-01-16 17:47:30 +01:00
Zoltan Kochan
a00f9e515c chore: use typescript-go (#10452) 2026-01-14 01:18:13 +01:00
Zoltan Kochan
cb367b9515 feat!: deprecate old settings that were replaced by allowBuilds (#10382) 2026-01-02 12:22:42 +01:00
Ryo Matsukawa
a8797c4e59 fix: handle EISDIR error when bin field points to directory (#10080)
close #9441
2025-10-13 10:00:06 +02:00
Ryo Matsukawa
50a47b0b63 fix: handle EPIPE errors when piping output (#10051) 2025-10-09 15:07:42 +02:00
Luis Hebendanz
9b9faa5c24 fix: retry filesystem operations on EAGAIN (#9959)
* fix: retry filesystem operations on EAGAIN

filesystem operations can raise EAGAIN to tell the application to try
again later. This is especially often the case under ZFS.

fix: move wrapped functions to graceful-fs directly

* fix: retry filesystem operations on EAGAIN

* fix: retry filesystem operations on EAGAIN

* fix: indexed-pkg-importer

* test: fix

* docs: add changeset

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2025-09-29 09:32:43 +02:00
Zoltan Kochan
87d3aa8bfc fix: fetching packument from AWS CodeArtifact (#9863)
close #9862
2025-08-15 12:10:22 +02:00
Zoltan Kochan
d1edf732ad feat: support installing Deno runtime (#9791)
* feat: support installing Deno runtime

* refactor: use npm registry to resolve deno version

* feat: wip

* feat: installing deno runtime

* style: fix

* test: fix

* test: deno

* test: fix

* feat: deno

* feat: deno

* feat: create zip fetcher

* style: fix

* refactor: node fetch

* feat: support a new binary fetcher

* test: fix

* feat: rename zip-fetcher to binary-fetcher

* refactor: change naming

* fix: windows

* refactor: rename packages

* refactor: deno resolver

* refactor: runtime resolvers

* refactor: binary fetcher

* refactor: runtime resolvers

* refactor: runtime resolvers

* refactor: create SingleResolution

* refactor: remove not needed change

* refactor: package requester

* docs: add changesets

* refactor: use VariationsResolution and AtomicResolution

* refactor: implement CR suggestions

* docs: add changesets

* fix: address comment in CR

* feat: update formatting of pnpm-lock.yaml
2025-07-30 11:27:07 +02:00
Zoltan Kochan
1ba2e15f2c feat: verify the integrity of Node.js artifacts (#9750) 2025-07-12 18:04:09 +02:00
Junxiao Shi
589ac1ffc7 fix(lifecycle): replace shell-quote with shlex (#9695)
* fix(lifecycle): replace shell-quote with shlex

close #9381

* fix: use shlex in @pnpm/worker

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2025-06-30 03:03:31 +02:00
Zoltan Kochan
7f520014a1 docs: add new sponsor 2025-06-25 01:39:12 +02:00
Zoltan Kochan
741fcd2adc feat: added support for Nushell to setup (#9510)
close #6476
2025-05-09 16:14:36 +02:00
Zoltan Kochan
fa1e69bd0c fix(deps): update @zkochan/cmd-shim to v7 (#9448)
close #9442
2025-04-22 23:39:04 +02:00
Khải
9c3dd03710 feat: add support for the jsr: protocol (#9358)
close #8941

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2025-04-20 11:51:51 +02:00
Zoltan Kochan
9bcca9f760 feat: config set local should save settings in pnpm-workspace.yaml (#9316) 2025-03-22 13:39:21 +01:00
Zoltan Kochan
cd8caece25 docs: update sponsors 2025-03-03 02:01:45 +01:00
Khải
331deacd45 chore(cspell): remove duplicated items (#9195) 2025-02-27 23:52:43 +01:00
Khải
e32b1a29e9 feat: update injected packages after run (#9100)
* feat: update injected packages after run (wip)

close #9081

* refactor: rename field

* feat: injectedPackages (wip)

* feat: findInjectedPackages (wip)

* feat: complete implementation

* test: findInjectedPackages

* docs: changeset

* refactor: be lazy

* chore: set `version` to `1000.0.0-0`

* feat: use hardlinks for injected packages

* refactor: just use `.modules.yaml`

* feat: debug logger

* refactor: `modulesDir` is unnecessary

* test: shouldUpdateInjectedFilesAfterRun

* fix(test): remove the test command

* test: updateInjectedPackagesAfterRun

* fix: eslint

* feat: rename config

* perf: diff to reduce fs operations

* perf: load source map only once

* chore(deps): remove unused dependencies

* fix: eslint

* refactor: use `symlink-dir`

* refactor: move type expr to an alias

* refactor: simplify types

* feat: reuse stats from the directory fetcher

* test: directories and symlinks

* feat: sort alphabetic

* test: diffDir

* test: rename a test

* test: remove nesting

* refactor: rename

* feat: remove buggy symlink support

* test: applyPatch

* docs: correct

* docs: fix

* test: extendFilesMap

* docs: remove outdated comment

* docs: remove unneeded comment

* test: fix

* test: more assertions

* test: DirPatcher

* test: more assertions

* test: more assertions

* test: just use `createDir`

* test: multiple patchers

* test: reuse stat results

* docs: consistent grammar

* test: workaround

* test: fix windows

* refactor: remove single-use `makeParent`

* refactor: remove nonsense test

How could I even misunderstand my own code?!

`Patcher.apply()` will never call stat on the files because they have all
been loaded to calculate `Patcher.patch`.

This test is therefore nonsense.

* feat: rename

* feat: rename again

* feat: remove `boolean`

* fix: broken lockfile

* test: use a fixture for testing sync injected deps

* test: refactor syne injected deps test

* test: refactor sync injected deps test

* test: refactor sync injected deps test

* refactor: rename injected deps to syncer

* refactor: change injected deps logger

* docs: update changeset

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2025-02-24 02:09:45 +01:00
Zoltan Kochan
f6006f2b4b feat: add an option to fail on unapproved dependency builds (#9071) 2025-02-11 00:26:25 +01:00
Khải
e8c2b173ca fix(overrides): move invalid peers to prod deps (#9000)
close #8978

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2025-01-28 18:00:59 +01:00
btea
2b49ee77c7 fix: install dependencies execute preprepare and postprepare scripts (#8989)
* fix: install dependencies execute preprepare script

* chore: remove unnecessary code

* fix: postprepare should run

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2025-01-26 20:31:00 +01:00
btea
12aebe29fe docs: README add Bluesky link (#8937) 2025-01-05 03:17:34 +01:00
Zoltan Kochan
cf9a8562eb docs: add new sponsor 2024-12-27 12:35:50 +01:00
Zoltan Kochan
ecb30d11b4 revert: "fix: installation dependency error in exFAT drive (#8872)"
This reverts commit 835b4e8f64.
2024-12-26 01:14:12 +01:00