mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-27 02:20:19 -04:00
fcdd50aaa773bc30f90bba767ca6c374646bf87e
34 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
fcdd50aaa7 | chore(release): 11.0.0-rc.3 | ||
|
|
72c1e050e9 |
feat: add pnpm pack-app command for packing CJS entries into standalone executables (#11312)
* fix: give each runtime variant its own global virtual store entry
When a runtime package (e.g. node@runtime:X.Y.Z) uses a variations
resolution, createFullPkgId() in @pnpm/deps.graph-hasher was hashing
the whole VariationsResolution — the same hash on every host — so the
global virtual store path collided between variants. Whichever variant
installed first won, and a later `pnpm add --libc=musl node@runtime:<v>`
silently reused the cached glibc (or macOS/Windows) binary.
The fix threads supportedArchitectures down to createFullPkgId so the
selected variant's integrity is used as the package fingerprint. Two
related cleanups land with it:
- Extract the platform-variant selection logic to @pnpm/resolving.resolver-base
as selectPlatformVariant/resolvePlatformSelector. The helper's libc
match also required a fix: a variant with no libc is the "default"
build, and a request for a non-default libc (e.g. musl) must require
an exact match so the default variant doesn't silently win.
- @pnpm/installing.package-requester's findResolution now delegates to
the shared helper, and the new supportedArchitectures param is plumbed
through calcDepState / calcGraphNodeHash / iterateHashedGraphNodes /
lockfileToDepGraph and their callers in deps-resolver, deps-restorer,
deps-installer, graph-builder, and building.after-install.
* feat: add pnpm build-sea command for building Node.js SEA executables
Adds `pnpm build-sea` under @pnpm/releasing.commands. Takes a CommonJS
entry file and a set of target triplets (linux-x64, linux-x64-musl,
linux-arm64, linux-arm64-musl, macos-x64, macos-arm64, win-x64,
win-arm64) and produces a standalone executable per target under
dist-sea/<target>/.
Each target's Node.js runtime is fetched via `pnpm add node@runtime:<v>
--os=<os> --cpu=<arch> --libc=<libc>` into $PNPM_HOME/build-sea/<target>-<v>/
so binaries are hardlinked from the global content-addressable store and
`pnpm store prune` can reclaim them.
Requires Node.js v25.5+ to perform the --build-sea injection. If the
running Node is older, a v25 binary is downloaded and used as the builder
automatically. macOS outputs are ad-hoc signed with codesign (on macOS)
or ldid (when cross-compiling from Linux), which is required because SEA
injection invalidates the binary's existing signature.
* fix(build-sea): reject malformed --target, --output-name and use mkdtemp for config
Addresses Copilot review feedback on the build-sea command:
- parseTarget() previously destructured the target string, silently
accepting extra `-` segments. Inputs like `linux-x64-musl-../../outside`
would pass validation and flow into path.join. Validation is now done
with a strict anchored regex.
- --output-name was passed into path.join() without sanitization, so a
caller could escape the output directory with path separators or `..`.
validateOutputName() now rejects anything that isn't a plain basename.
- The per-target SEA config file was written to a predictable path under
os.tmpdir() (derived from the target name and Date.now()), which is
unsafe on multi-user systems. It now lives inside a fresh mkdtemp()
directory and is opened with the exclusive "wx" flag.
- New test cases cover extra-segment targets, uppercase/whitespace
variants, and the full matrix of invalid --output-name inputs.
* rename: build-sea → pack-app
`build-sea` required knowing what a SEA is. `pack-app` is self-describing,
doesn't collide with pnpm's existing `bin` concept, and parallels the
existing `pack` command.
- Command name: build-sea → pack-app
- Default output dir: dist-sea → dist-app
- Error codes: PACK_APP_* (was BUILD_SEA_*)
- Export/type: packApp / PackAppOptions (was buildSea / BuildSeaOptions)
- Install cache dir: $PNPM_HOME/pack-app (was $PNPM_HOME/build-sea)
The Node.js `--build-sea` flag name itself is unchanged — that's a
Node.js feature and outside this project's naming.
* fix(pack-app): reject directory entries, pin builder to >=25.5, refuse macOS target on Windows
Addresses Copilot review feedback on the pack-app command:
- entry validation now rejects non-file paths (directories, symlinks to
non-files) with a dedicated PACK_APP_ENTRY_NOT_FILE instead of
surfacing a less actionable error later in the SEA build.
- DEFAULT_BUILDER_SPEC was the bare major ("25"), which would satisfy
with 25.0.x if that version is still present — those point releases
predate --build-sea support. Tightened to ">=25.5.0 <26.0.0" so the
download is guaranteed to support the flag without ever crossing a
major.
- adHocSignMacBinary() silently skipped re-signing on Windows hosts.
Now throws PACK_APP_MACOS_SIGN_UNSUPPORTED_HOST with a hint to build
the target on macOS/Linux or re-sign manually.
- resolvePlatformSelector() JSDoc now matches what the code actually
does (picks the first entry when it is not "current"; later entries
are ignored).
- New test case covers the directory-as-entry rejection.
* refactor(pack-app): switch target OS names to process.platform constants
Previously `pack-app` accepted `macos-*` / `win-*` as the OS portion of a
target triplet and translated them to `darwin` / `win32` internally. The
translation layer made the CLI surface inconsistent with the values that
`pnpm add --os=…` and `supportedArchitectures.os` already use, and added
a small footgun (e.g. users setting `supportedArchitectures: { os: [darwin] }`
but typing `macos-arm64` for pack-app).
The supported target OS set is now `linux | darwin | win32`, matching
`process.platform`. Old inputs like `macos-arm64` or `win-x64` now fail
validation with a clear error pointing to the new naming. The internal
parseTarget helper drops its TARGET_OS_MAP lookup entirely.
This is a change to an unreleased command so there is no back-compat
concern. pnpm's own artifact directory names (`pnpm/artifacts/macos-*/`,
`pnpm/artifacts/win-*/`) are an internal implementation detail and are
not affected by this change.
* feat(pack-app): read defaults from pnpm.app in package.json
Every pack-app flag (--entry, --target, --node-version, --output-dir,
--output-name) can now be preconfigured in the project's package.json
under a new "pnpm.app" object:
{
"name": "my-cli",
"pnpm": {
"app": {
"entry": "dist/index.cjs",
"targets": ["linux-x64", "darwin-arm64", "win32-x64"],
"nodeVersion": "25",
"outputDir": "release",
"outputName": "my-cli"
}
}
}
CLI flags always win. --target replaces the configured list rather than
appending, so a user can narrow the default set at the command line.
The config loader is strict: unknown keys under pnpm.app and any
type-mismatched values throw PACK_APP_INVALID_CONFIG so mistakes surface
at invocation time instead of silently being ignored.
Chose pnpm.app over pnpm.packApp because it's the shorter, cleaner
namespace for anything related to the app bundle (future sibling
commands like run-app / deploy-app could share the same object without
a naming clash). Chose package.json over pnpm-workspace.yaml because
the config is inherently per-project, whereas pnpm-workspace.yaml is
workspace-root-only.
* fix(pack-app): deterministic libc selection and stricter output-name validation
Addresses Copilot review feedback:
- ensureNodeRuntime() now always passes an explicit --libc for linux
targets. Without a suffix, linux-x64 and linux-arm64 default to
--libc=glibc instead of letting the user's supportedArchitectures.libc
config or the host's detected libc decide the variant. The install
cache directory mirrors this, so glibc and musl variants are always
distinct (linux-x64-glibc vs linux-x64-musl).
- resolveBuilderBinary() now pins the host libc when downloading a
builder Node on Linux. A user whose config sets supportedArchitectures.libc
to musl no longer ends up with a musl Node that the glibc host cannot
execute.
- validateOutputName() rejects Windows-invalid filename characters
(<>:"|?* and NUL), Windows reserved device names (CON, NUL, COM1, etc.),
and names ending in a dot or space — problems surface at invocation
time rather than during writeFile(outputFile, ...) on Windows.
- lockfileToDepGraph variants tests no longer derive the "host"
variant from process.platform/process.arch; they always pass an
explicit supportedArchitectures selector so the expectations hold on
any CI host (including Alpine/musl).
* chore: add "toctou" to cspell wordlist
`TOCTOU` (time-of-check-to-time-of-use) is the standard term for the
race-condition class the pack-app SEA-config comment describes. Adding
it to the wordlist unblocks the Lint CI step.
* fix: lint
|
||
|
|
53668a42b8 |
fix: support explicit versions and --no-commit-hooks / --no-git-tag-version in pnpm version (#11299)
* fix: support explicit versions and --no-commit-hooks / --no-git-tag-version in `pnpm version` Registers options under their canonical names so nopt correctly parses the `--no-*` variants, accepts an explicit semver argument alongside bump types, and creates a git commit + annotated tag for the bump (honoring `--no-git-tag-version`, `--no-commit-hooks`, `--sign-git-tag`, `--message`, and `--tag-version-prefix`). Also fixes `--no-git-checks` which was parsed incorrectly. Closes #11271. * chore: add gpgsign and newversion to cspell; set gpg sign config in version test * fix: address Copilot review feedback on pnpm version * fix: skip git commit and tag in recursive version runs * fix: address Copilot review feedback on pnpm version |
||
|
|
96ece9d736 | chore(release): 11.0.0-rc.2 | ||
|
|
f7c23231a9 | chore(release): 11.0.0-rc.1 | ||
|
|
2410cf4092 |
feat: add pnpm docs command and home alias (#11244)
* feat: add pnpm docs command and home alias * chore: update manifests * fix: address review comments for pnpm docs command - Remove 'docs' and 'home' from NOT_IMPLEMENTED_COMMANDS to prevent not-implemented handlers from overriding the real implementations - Change fallback URL from npmjs.com to npmx.dev - Remove bugs URL as a docs fallback (it's an issue tracker, not docs) - Fix ESM mock in tests: use jest.unstable_mockModule instead of jest.mock * refactor: use open package for browser opening in promptBrowserOpen Replace the hand-rolled platform-specific execFile logic with the open npm package, which handles WSL, Docker-in-WSL, and Windows edge cases better. This removes the execFile dependency injection from promptBrowserOpen, OtpContext, LoginContext, and SharedContext. * fix: address copilot review comments - docs: use www.npmjs.com fallback (not npmx.dev) and validate homepage URL is http(s) before opening - promptBrowserOpen: validate authUrl protocol before passing to open(), and guard against synchronous throws from open() * fix: restore npmx.dev fallback for pnpm docs * chore: expand changeset with web-auth refactor impact --------- Co-authored-by: Zoltan Kochan <z@kochan.io> |
||
|
|
06d6c2d405 | chore(release): 11.0.0-rc.0 | ||
|
|
68a951006e |
test: update registry-mock to 6.0.0 stable and use pnpm view in tests (#11227)
* test: update registry-mock to 6.0.0 stable and use pnpm view in tests Update @pnpm/registry-mock from 6.0.0-6 to 6.0.0 stable release. Replace npm view with pnpm view in test helpers now that pnpm has native view/dist-tag commands. Unskip the nodeRuntime test that was blocked on the registry-mock republish. * chore: update pnpm to beta 8 * feat: support versions, dist-tags, and time field selectors in pnpm view The view command now exposes versions (as an array of version strings), dist-tags, and time from registry metadata. Single-field --json output returns the raw value instead of wrapping it in an object, matching npm behavior. This allows tests to use pnpm view instead of npm view. |
||
|
|
fb58648b00 |
test: update registry-mock to v6 and fix test fixtures (#11223)
- Update `@pnpm/registry-mock` from 5.2.4 to 6.0.0-6 - Fix auth tests to use bearer token from `globalSetup` instead of hardcoding credentials - Replace hardcoded integrity checksums with `getIntegrity()` from registry-mock in `customResolvers` tests - Add `prepareFixtureWithIntegrity()` helper in deps-restorer tests to dynamically patch `@pnpm.e2e` integrity values in fixture lockfiles at runtime, so they don't go stale when registry-mock is updated - Fix `workspace-external-depends-deep` fixture's current lockfile (was missing `packages/f` and `packages/g` importers) - Remove unnecessary credentials from `gitChecks` tests (they reject before any registry interaction) |
||
|
|
853be661d8 |
feat: add native pnpm dist-tag command (#11218)
Implement dist-tag ls, add, and rm subcommands natively instead of delegating to npm. Follows the same pattern as the recently added deprecate and unpublish commands. |
||
|
|
b103439d9a |
refactor(test): extract shared DEFAULT_OPTS into @pnpm/testing.command-defaults (#11208)
12 command test suites had near-identical ~50-field DEFAULT_OPTS objects copy-pasted between them. Extract the common fields into a single shared package so each suite only declares its overrides. |
||
|
|
45a6cb6b2a |
refactor(auth): unify auth/SSL into structured configByUri (#11201)
Replaces the dual `authConfig` (raw .npmrc) + `authInfos` (parsed auth) + `sslConfigs` (parsed SSL) pattern with a single structured `configByUri: Record<string, RegistryConfig>` field on Config.
### New types (`@pnpm/types`)
- **`RegistryConfig`** — per-registry config: `{ creds?: Creds, tls?: TlsConfig }`
- **`Creds`** — auth credentials: `{ authToken?, basicAuth?, tokenHelper? }`
- **`TlsConfig`** — TLS config: `{ cert?, key?, ca? }`
### Key changes
- Rewrite `createGetAuthHeaderByURI` to accept `Record<string, RegistryConfig>` instead of raw .npmrc key-value pairs
- Eliminate duplicate auth parsing between `getAuthHeadersFromConfig` and `getNetworkConfigs`
- Remove `authConfig` from the install pipeline (`StrictInstallOptions`, `HeadlessOptions`), replaced by `configByUri`
- Remove `sslConfigs` from Config — SSL fields now live in `configByUri[uri].tls`
- Remove `authConfig['registry']` mutation in `extendInstallOptions` (default registry now passed directly to `createGetAuthHeaderByURI`)
- `authConfig` remains on Config only for raw .npmrc access (config commands, error reporting, config inheritance)
### Security
- tokenHelper in project .npmrc now throws instead of being silently stripped
- tokenHelper execution uses `shell: false` to prevent shell metacharacter injection
- Basic auth uses `Buffer.from().toString('base64')` instead of `btoa()` for Unicode safety
- Dispatcher only creates custom agents when entries actually have TLS fields
|
||
|
|
b5d93c6ba9 |
refactor(config): remove rawLocalConfig and force* hoist flags (#11199)
rawLocalConfig detected whether hoist settings were explicitly set. In v11, config values are always authoritative. - Remove rawLocalConfig from ConfigContext, config reader, inheritPickedConfig, UniversalOptions - Remove forceHoistPattern, forcePublicHoistPattern, forceShamefullyHoist — validateModules always checks now - Simplify save-workspace-protocol check - Remove dead rawLocalConfig overrides in deploy/patchCommit |
||
|
|
3033bee430 |
refactor(config): split Config interface into settings + runtime context (#11197)
* refactor(config): split Config interface into settings + runtime context
Create ConfigContext for runtime state (hooks, finders, workspace graph,
CLI metadata) and keep Config for user-facing settings only. Functions
use Pick<Config, ...> & Pick<ConfigContext, ...> to express which fields
they need from each interface.
getConfig() now returns { config, context, warnings }. The CLI wrapper
returns { config, context } and spreads both when calling command
handlers (to be refactored to separate params in follow-up PRs).
Closes #11195
* fix: address review feedback
- Initialize cliOptions on pnpmConfig so context.cliOptions is never undefined
- Move rootProjectManifestDir assignment before ignoreLocalSettings guard
- Add allProjectsGraph to INTERNAL_CONFIG_KEYS
* refactor: remove INTERNAL_CONFIG_KEYS from configToRecord
configToRecord now accepts Config and ConfigContext separately, so
context fields are never in scope. Only auth-related Config fields
(authConfig, authInfos, sslConfigs) need filtering.
* refactor: eliminate INTERNAL_CONFIG_KEYS from configToRecord
configToRecord now receives the clean Config object and explicitlySetKeys
separately (via opts.config and opts.context), so context fields are
never in scope. main.ts passes the original split objects alongside
the spread for command handlers that need them.
* fix: spelling
* fix: import sorting
* fix: --config.xxx nconf overrides conflicting with --config CLI flag
When `pnpm add` registers `config: Boolean`, nopt captures
--config.xxx=yyy as the --config flag value instead of treating it
as a nconf-style config override. Fix by extracting --config.xxx args
before nopt parsing and re-parsing them separately.
Also rename the split config/context properties on the command opts
object to _config/_context to avoid clashing with the --config CLI option.
|
||
|
|
96704a1c58 |
refactor(config): rename rawConfig to authConfig, add nodeDownloadMirrors, simplify config reader (#11194)
Major cleanup of the config system after migrating settings from `.npmrc` to `pnpm-workspace.yaml`.
### Config reader simplification
- Remove `checkUnknownSetting` (dead code, always `false`)
- Trim `npmConfigTypes` from ~127 to ~67 keys (remove unused npm config keys)
- Replace `rcOptions` iteration over all type keys with direct construction from defaults + auth overlay
- Remove `rcOptionsTypes` parameter from `getConfig()` and its assembly chain
### Rename `rawConfig` to `authConfig`
- `rawConfig` was a confusing mix of auth data and general settings
- Non-auth settings are already on the typed `Config` object — stop duplicating them in `rawConfig`
- Rename `rawConfig` → `authConfig` across the codebase to clarify it only contains auth/registry data from `.npmrc`
### Remove `rawConfig` from non-auth consumers
- **Lifecycle hooks**: replace `rawConfig: object` with `userAgent?: string` — only user-agent was read
- **Fetchers**: remove unused `rawConfig` from git fetcher, binary fetcher, tarball fetcher, prepare-package
- **Update command**: use `opts.production/dev/optional` instead of `rawConfig.*`
- **`pnpm init`**: accept typed init properties instead of parsing `rawConfig`
### Add `nodeDownloadMirrors` setting
- New `nodeDownloadMirrors?: Record<string, string>` on `PnpmSettings` and `Config`
- Replaces the `node-mirror:<channel>` pattern that was stored in `rawConfig`
- Configured in `pnpm-workspace.yaml`:
```yaml
nodeDownloadMirrors:
release: https://my-mirror.example.com/download/release/
```
- Remove unused `rawConfig` from deno-resolver and bun-resolver
### Refactor `pnpm config get/list`
- New `configToRecord()` builds display data from typed Config properties on the fly
- Excludes sensitive internals (`authInfos`, `sslConfigs`, etc.)
- Non-types keys (e.g., `package-extensions`) resolve through `configToRecord` instead of direct property access
- Delete `processConfig.ts` (replaced by `configToRecord.ts`)
### Pre-push hook improvement
- Add `compile-only` (`tsgo --build`) to pre-push hook to catch type errors before push
|
||
|
|
c7203b99ad |
feat!: set default minimumReleaseAge to 1 day (1440 minutes) (#11158)
set default minimumReleaseAge to 1 day --------- Co-authored-by: Zoltan Kochan <z@kochan.io> |
||
|
|
8bba5c3858 |
refactor(config): only read auth/registry from .npmrc, add registries to pnpm-workspace.yaml (#11189)
Replace the unmaintained @pnpm/npm-conf package with a purpose-built module that reads only auth/registry-related settings from .npmrc files using read-ini-file + @pnpm/config.env-replace (both already deps). All non-registry settings (hoist-pattern, node-linker, etc.) are now only read from pnpm-workspace.yaml, CLI options, or environment variables. Registry-related settings (auth tokens, registry URLs, SSL certs, proxy settings) continue to be read from .npmrc for migration compatibility, and can also be set in pnpm-workspace.yaml. New modules: - loadNpmrcFiles.ts: reads .npmrc from standard locations, filters to auth/registry keys, returns structured layers - npmConfigTypes.ts: inlined npm config type definitions - npmDefaults.ts: inlined npm defaults (registry, unsafe-perm, etc.) |
||
|
|
de3dc74439 |
feat(auth): keyboard event to open browser (#11148)
* feat(auth): add "Press ENTER to open in browser" during web authentication During web-based authentication (login, publish), users can now press ENTER to open the authentication URL in their default browser. The background token polling continues uninterrupted, so users who prefer to authenticate on their phone can still do so without pressing anything. The implementation uses Node's readline module (not raw mode), so Ctrl+C and Ctrl+Z continue to work normally. It is fully error-tolerant: if the keyboard listener or browser opening fails, a warning is printed and the polling continues. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix(auth): inject readline and execFile directly, not wrapper functions Address review feedback: - Remove defaultListenForEnter and defaultOpenBrowser wrapper functions - Inject readline module and execFile function directly via context - DEFAULT_CONTEXT now references modules directly (no closures) - Use switch for platform detection, default = no browser prompt - Rename pollWithBrowserOpen → offerToOpenBrowser (clearer name) - Add platform-specific tests (darwin, win32, linux, freebsd) - Use PassThrough streams for stdin mocks in tests https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix(auth): fix CI type errors in test mocks - Type jest.fn() mocks for readline.createInterface properly - Use PassThrough streams for stdin mocks in releasing/commands tests https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * refactor(auth): use generic Stdin parameter to eliminate PassThrough in tests Per review feedback, add a generic Stdin type parameter to context interfaces. This ties process.stdin and readline.createInterface together through the same type, so tests can use simple { isTTY: true } mocks instead of requiring PassThrough streams. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix(auth): propagate Stdin generic to releasing/commands OtpContext The OtpContext in releasing/commands extends BaseOtpContext from web-auth. Now that BaseOtpContext is generic, the local OtpContext and publishWithOtpHandling must also be generic so tests can use simple stdin mocks without PassThrough. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix: sort imports in releasing/commands otp.ts https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * refactor(auth): use .bind() for readline injection instead of generics Per review feedback, revert the generic Stdin approach and instead use readline.createInterface.bind(null, { input: process.stdin }) as the injectable dependency. This avoids generics proliferation while keeping the context clean — no arrow functions or closures in DEFAULT_CONTEXT. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * feat(publish): add "Press ENTER to open in browser" during publish OTP Wire up createReadlineInterface and execFile in the publish SHARED_CONTEXT so that pnpm publish also offers to open the browser during web-based OTP authentication. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix(auth): improve browser-open prompt message Change "Press ENTER to open in browser..." to "Press ENTER to open the URL in your browser." The old message implied the user should press Enter. The new wording presents it as an available action, not an instruction — users can also scan the QR code or copy-paste the URL. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * style: remove unnecessary arrow wrapper around createMockReadlineInterface https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * docs: explain why Enter keypress is fire-and-forget, not awaited Add a comment explaining that only pollPromise is awaited — the Enter listener is intentionally not part of a Promise.all. This prevents a future refactor from reintroducing the npm bug where authentication blocks until Enter is pressed, even when the user authenticates on another device. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * docs: add permalink to npm's Promise.all bug in comment Link to the specific npm-profile commit (d1a48be4259) so the comment remains accurate even if npm fixes the bug in the future. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix: correct line numbers in npm-profile permalink (L85-L98) https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * style: apply review suggestion for npm-profile permalink format https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * style: remove duplicate line in npm-profile comment https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix: shadow global process instead of renaming to proc Destructure as `process` (not `proc`) so the global `process` is shadowed, preventing accidental direct access to it. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix: merge process fields in test mock contexts Restructure createMockContext to merge process fields instead of replacing the entire object. Tests that only need to override platform or stdin no longer need to redundantly provide the other. Also adds a test for undefined platform (default: case). https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix: use Omit+Partial for process overrides in test mock contexts The process field spread `...overrides?.process` merges at runtime but TypeScript still requires all fields in the override type. Fix by typing the process override as Partial via Omit<..., 'process'> & { process?: Partial<...> }. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * refactor: extract a type alias * refactor: extract MockContextOverrides type alias in remaining tests https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * refactor(auth): extract process types, use NodeJS.Platform, clean up tests - Extract OfferToOpenBrowserProcess interface from inline process type - Extract LoginProcess interface from inline process type in LoginContext - Use NodeJS.Platform instead of string for platform fields (prevents typos) - Rename simulateEnter → simulateEnterKeypress (clarify it's the key) - Convert single-return functions to arrow expressions in tests - Update test descriptions to say "Enter key" / "Enter keypress" https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * refactor(auth): rename offerToOpenBrowser → promptBrowserOpen Per review feedback, "offer to open browser" was mouthful. Renamed function, file, and all associated types (OfferToOpenBrowser* → PromptBrowserOpen*). https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * docs: drop "IMPORTANT" * refactor(auth): extract OtpProcess interface from inline process type https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix(auth): validate authUrl before passing to execFile On Windows, cmd.exe re-parses execFile arguments with full shell grammar, so metacharacters (&, |, ^, etc.) in the URL would be interpreted as operators. Validate that authUrl is a well-formed http(s) URL before passing it to the platform browser command. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * test(auth): add regression test for URLs with query parameters on win32 Verifies that URLs containing & and other query string characters are passed through to execFile as-is on the win32 platform. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix(auth): escape cmd.exe metacharacters in Windows browser open URL On Windows, cmd.exe re-parses execFile arguments and treats & | < > ^ % as operators. Escape these with ^ so query strings in auth URLs (e.g. ?token=abc&redirect=...) are not split by cmd.exe. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix(auth): use canonicalized URL and expand cmd.exe escape set - Use parsedUrl.href (canonicalized by new URL()) instead of the raw authUrl string, ensuring percent-encoding of spaces and special chars. - Expand cmd.exe metacharacter escaping to include () and ! in addition to & | < > ^ %, covering grouping operators and delayed expansion. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * docs(auth): document Windows browser-opening edge cases Explain why cmd /c start is used instead of ShellExecuteW (not callable from Node.js without a native addon), why alternatives like explorer.exe, rundll32, and PowerShell are unreliable, and note that a Rust/N-API addon could replace this in the future. https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW * fix: fix cspell errors in Windows browser-open comment Reword to avoid unknown words "rundll" and "metacharacter". https://claude.ai/code/session_01UtDnjrNQ2Cc3GLAPR8BrrW --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
d6b8e281b6 | chore: use pn instead of pnpm (#11124) | ||
|
|
36b3826f7b |
feat: make clean/setup/deploy prefer user scripts over built-in commands (#11118)
* feat: make clean/setup/deploy prefer user scripts over built-in commands When a project's package.json has a script named "clean", "setup", or "deploy", running `pnpm clean/setup/deploy` now executes the script instead of the built-in command. This prevents surprising behavior for users with existing scripts. When running from a workspace subdirectory where the root package.json has one of these scripts, an error is thrown with guidance on how to proceed. Added "purge" as an alias for the built-in clean command, which always runs the built-in regardless of scripts. Closes #6816 * feat: also make rebuild prefer user scripts over the built-in * refactor: move scriptOverride to command definitions Each command now declares `scriptOverride = true` instead of a centralized list in main.ts. All command names including aliases are overridable by same-named scripts. * refactor: rename scriptOverride to overridableByScript * test: add e2e tests for script override behavior in clean/purge * fix: address review feedback - Fix JSDoc to reflect that aliases are also overridable by scripts - Update npm_command env var to 'run-script' when redirecting to run - Add 'purge' alias to clean command help text |
||
|
|
9496b2c61b |
fix: remove --workspace flag from version command (#11115)
* fix: remove --workspace flag from version command, use only --recursive The --workspace/--workspaces flags were incorrectly added as synonyms for --recursive in the version command. In pnpm, --recursive (-r) is the standard convention for applying commands across workspace packages. Recursive versioning now only activates with the explicit -r flag. * test: improve version command test coverage Add tests for major/patch bumps, --json output, --allow-same-version, invalid version handling, missing name/version, empty params, and recursive mode with workspace packages including JSON output, skipping unnamed packages, and verifying --recursive is required. * test: use expect().rejects instead of try/catch in version tests Avoids silent passes when the handler doesn't throw. |
||
|
|
d4a1d734b6 |
feat: pnpm login (#11094)
* refactor: extract web auth QR code and polling into @pnpm/network.web-auth Extract generateQrCode() and pollForWebAuthToken() from releasing/commands into a new shared package so that both `pnpm publish` and the upcoming `pnpm login` can reuse the web-based authentication flow with QR code display and doneUrl polling. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * feat: implement `pnpm login` command Add `pnpm login` (and `pnpm adduser` alias) for authenticating with npm registries. The command: - Tries web-based login first (POST /-/v1/login), displaying a QR code and polling for the token using @pnpm/network.web-auth - Falls back to classic username/password/email login (PUT /-/user/ org.couchdb.user:<username>) when web login is not supported (404/405) - Saves the received auth token to the user's global rc file Also fixes a tsgo build issue in releasing/commands where OtpWebAuthFetchOptions was used as a local type alias but was only available as a re-exported name. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * fix: resolve spellcheck issues in login test https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * fix: correct alphabetical ordering for meta-updater https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * chore: add meta-updater generated tsconfig files https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * fix: add explicit return type to prompt mock for tsgo compatibility https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * fix: use @pnpm/network.fetch instead of globalThis.fetch Switch from globalThis.fetch to fetchWithAgent from @pnpm/network.fetch so that pnpm login respects proxy settings (httpProxy/httpsProxy/noProxy), custom SSL certificates (ca/cert/key), strictSsl, and retry configuration. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor: improve login fetch types and use URL constructor - Type LoginContext.fetch using WebAuthFetchOptions/WebAuthFetchResponse from @pnpm/network.web-auth, extended with text() and wider method - Replace regex-based URL construction with new URL() constructor - Remove redundant LoginFetchInit type https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor: match publish pattern for dependency injection - Static DEFAULT_CONTEXT constant instead of createDefaultContext factory - context = DEFAULT_CONTEXT default parameter instead of context?: Partial - Destructure context in function signatures for natural calling - Use plain fetch from @pnpm/network.fetch (like SHARED_CONTEXT in publish) - Context contains only side-effect functions and modules, not config https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor: use typeof fetch instead of custom fetch types Remove LoginFetchOptions and LoginFetchResponse. Type LoginContext.fetch as typeof fetch from @pnpm/network.fetch directly, eliminating all casts. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * fix: remove placeholder username from login success message Web login doesn't return a username, so just report the registry. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor: use tempDir from @pnpm/prepare instead of manual tmp dirs https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * chore: update tsconfig references for @pnpm/prepare https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor: inject readSettings/writeSettings for fully pure tests Add readSettings and writeSettings to LoginContext so tests need no filesystem side effects. Remove @pnpm/prepare devDependency. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor: remove DEFAULT_CONTEXT from tests, use pure test context Tests now construct their own TEST_CONTEXT with all no-op mocks, eliminating any reliance on real side-effectful functions. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * test: use distinct opts per test, assert URLs and config paths Each test now uses a different registry and configDir to verify URL construction, config key generation, and save path are correct for non-default options. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * test: throw on unexpected mock calls instead of silent fallbacks All mock functions in TEST_CONTEXT now throw on unexpected calls, ensuring tests fail loudly if the code makes unanticipated side effects. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * test: use IANA-reserved example.com domains in test URLs Replace custom.registry.io and private.reg.co with example.com and example.org (RFC 2606 reserved) to prevent domain squatting risks. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * test: use deterministic Date mock instead of native Date https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * test: assert globalInfo calls, throw on unexpected ones Default globalInfo in TEST_CONTEXT now throws. Each test overrides it to capture messages and asserts the expected output. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * fix: use inferred type for fetch url parameter in tests Drop explicit `string` annotation so the parameter matches the `RequestInfo` type expected by the fetch signature. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * fix: resolve type errors in login test mock fetch Use mockResponse helper with `as any` cast to satisfy the Response type, and String(url) for RequestInfo-to-string conversion. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * chore: add tsconfig.lint.tsbuildinfo to .gitignore https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor: replace typeof fetch with explicit LoginFetchResponse/LoginFetchOptions types Derive the fetch signature from actual call-site usage instead of coupling to the concrete @pnpm/network.fetch type. This lets test mocks return plain objects without casts. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * chore: gitignore generated pn/pnpx/pnx artifacts These files are created by setup.js during preinstall and should not be tracked. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor: remove unnecessary backwards-compat aliases from otp.ts Remove Otp-prefixed re-exports (OtpWebAuthFetchOptions, OtpWebAuthFetchResponse, OtpWebAuthTimeoutError) that only existed as backwards-compatibility shims. Update the test to import directly from @pnpm/network.web-auth. Restore the named OtpDate interface that was unnecessarily inlined. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * test(web-auth): add comprehensive unit tests for @pnpm/network.web-auth Add dependency-injected unit tests covering: - WebAuthTimeoutError: properties, code, hint, message - generateQrCode: basic output and input differentiation - pollForWebAuthToken: happy path, fetch argument passing, Retry-After handling (valid, non-finite, null, sub-interval, capped to remaining timeout, timeout during retry wait), error recovery (fetch throws, non-ok response, json parse error, missing token, empty token, multiple consecutive errors), custom timeout, poll interval timing All tests use fake Date.now() and setTimeout — no real timers or side effects. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * fix(web-auth): fix TS2339 compile errors in test assertions Replace `.catch((e: WebAuthTimeoutError) => e)` pattern with `rejects.toMatchObject()` to avoid `string | WebAuthTimeoutError` union type issue when accessing `.timeout` property. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * feat(web-auth,login): extract shared OTP handling and add OTP support to login - Create `withOtpHandling<T>()` in `@pnpm/network.web-auth` that wraps any operation with EOTP challenge detection, web auth flow, and classic OTP prompting. - Refactor `publishWithOtpHandling` to delegate to the shared function. - Add OTP handling to `pnpm login`'s classic (CouchDB) login flow: detects 401 + `www-authenticate: otp` header and retries with the OTP code (or web auth token) in the `npm-otp` header. - Remove overly strict `this: this` constraints from WebAuthFetchResponse interfaces to improve cross-package type compatibility. - Add 13 unit tests for `withOtpHandling` (classic + webauth flows). - Add 4 login OTP tests (classic OTP, webauth OTP, non-401, non-otp 401). https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * fix(login): use word-boundary regex for URL assertion in test Replace `m.includes(url)` with a regex that checks the URL is bounded by whitespace or string boundaries, addressing the CodeQL "incomplete URL substring sanitization" finding. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor(login): use toContainEqual + stringMatching for URL assertion Replace manual `.some()` with Jest's `toContainEqual(expect.stringMatching(...))` for better error messages on failure. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor(web-auth): use expect.any(String) instead of typeof check https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor(web-auth): consolidate multi-property assertions Use toMatchObject and toEqual instead of separate per-property expects. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * docs: explain why npm-auth-type header is sent unconditionally https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor: remove unused re-exports and add missing test coverage Remove dead re-exports of OtpHandlingPromptOptions and OtpHandlingPromptResponse from releasing/commands/src/publish/otp.ts. Add tests for: - LOGIN_MISSING_CREDENTIALS (empty username in classic login) - LOGIN_NO_TOKEN (registry returns success without token) - LOGIN_INVALID_RESPONSE (web login returns incomplete response) - isWebLoginNotSupported with 405 status code https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor(login): rename readSettings/writeSettings to safeReadIniFile/writeIniFile Use the actual function names in the LoginContext interface instead of abstract names, matching the implementations they wrap. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor(otp): remove unnecessary re-exports from otp.ts OtpNonInteractiveError, OtpSecondChallengeError, and OtpHandlingEnquirer were re-exported only for the test file, which can import them directly from @pnpm/network.web-auth. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor(otp): remove unused SHARED_CONTEXT re-export All consumers already import SHARED_CONTEXT directly from ./utils/shared-context.js, making this re-export dead code. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor(login): extract LoginDate and LoginEnquirer interfaces Extract named interfaces for the Date and enquirer members of LoginContext instead of inlining their types. https://claude.ai/code/session_01YHYqGAAmZ1a9XMWoV7nG4S * refactor: stop renaming Claude Code Web didn't rename them thoroughly, so I had to do it myself * docs: correct the lines Why did Claude Code Web misaligned? * refactor: strictly type `LoginFetchOptions.headers` * docs: remove redundant comments * refactor: inline `npm-otp` * refactor: inline `headers` * feat: add `WebLoginError.responseText` * refactor: rename `statusCode` into `httpStatus` * refactor(login): extract ClassicLoginError subclass from PnpmError Extract the LOGIN_FAILED error into a dedicated ClassicLoginError class with httpStatus and responseText properties, matching the WebLoginError pattern. https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * refactor: remove unnecessary import * docs(changeset): correct a changeset * docs(changeset): re-add `releasing.commands` * refactor(web-auth): split monolithic test file into per-module files Split index.test.ts into four files matching the source structure: - WebAuthTimeoutError.test.ts - generateQrCode.test.ts - pollForWebAuthToken.test.ts - withOtpHandling.test.ts https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * refactor: remove unnecessary `as const` * refactor: remove unnecessary `as const` * chore: undo Claude's BS * refactor: extract `LoginEnquirerOptions` * refactor: move types closer to their usesites * refactor: remove simple type alias * fix: type errors * refactor(login): inject readIniFile instead of safeReadIniFile in context The context object should only contain external dependencies. safeReadIniFile is a local wrapper, not an external dependency, so inject readIniFile (from read-ini-file) instead and pass it to safeReadIniFile as a parameter. https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * test(login): add coverage for safeReadIniFile ENOENT handling Test that login succeeds with empty settings when the config file does not exist (ENOENT), and that non-ENOENT errors (e.g. EACCES) are properly propagated. https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * refactor: fix ugliness * refactor: just pass context object * refactor: destructure `context` * refactor: pass the `context` object * refactor: destructure `context` * refactor: pass `context` object directly * refactor: remove unnecessary parenthesis * fix: remove unused import * refactor: remove unnecessary parentheses from single-param arrows in tests https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * refactor: extract `LoginFetchResponseHeaders` * fix(login): remove inline default from --registry option description No other pnpm command includes "(default: ...)" in option descriptions. https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * refactor(tests): enforce realistic mock response behavior - Add createMockResponse helpers that enforce single body consumption (calling text() or json() twice, or both, throws an error) - Default headers.get to throwing on unexpected calls, forcing tests to explicitly provide headers when the code under test reads them - Replace all inline response objects with createMockResponse calls https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * fix: formatting * refactor: reuse * docs: clarify what the error is actually about * docs: consistent error message * refactor: use consistent error message convention in test mocks Capitalize and use "Unexpected call to <thing>" pattern instead of AI-generated "unexpected X call" messages. https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * refactor: expand inline process mock objects to multi-line https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * refactor(login): extract PnpmError subclasses and use stricter test assertions Extract LoginNonInteractiveError, LoginInvalidResponseError, LoginMissingCredentialsError, and LoginNoTokenError subclasses instead of throwing PnpmError directly. Update test assertions to use the const promise pattern with toHaveProperty checks on both code and message, matching the convention used elsewhere in the codebase. https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * refactor: undo ai's nonsensical deletion * refactor: simplify * refactor: rename OtpHandling* types to Otp* for brevity OtpHandlingContext → OtpContext OtpHandlingEnquirer → OtpEnquirer OtpHandlingPromptOptions → OtpPromptOptions OtpHandlingPromptResponse → OtpPromptResponse The OtpHandling prefix was named after the function (withOtpHandling) rather than the domain concept. https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * refactor: extract `OtpDate` * refactor: reuse * fix: eslint * refactor: add OtpRequiredError with body validation and globalWarn - Add OtpRequiredError class with static fromUnknown() that validates the EOTP error body shape and returns either a validated error or an OtpBodyWarning when fields have unexpected types - Add globalWarn to OtpContext so withOtpHandling can warn on bad body shapes instead of silently dropping them - Update throwIfOtpRequired in login.ts to pass raw body through so validation happens in withOtpHandling via fromUnknown - Add tests for bad body shapes (wrong types for authUrl/doneUrl) - Add tests for OtpRequiredError.fromUnknown - Propagate globalWarn through LoginContext, DEFAULT_CONTEXT, SHARED_CONTEXT, and all test mocks https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * docs: remove misleading comment from throwIfOtpRequired The comment referenced downstream machinery (OtpRequiredError.fromUnknown) that the reader shouldn't need to know about at this call site. https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * refactor: replace Object.assign hack with OtpRequiredError in throwIfOtpRequired throwIfOtpRequired now validates the raw response body via OtpRequiredError.fromUnknown and throws a proper OtpRequiredError instead of monkey-patching properties onto a plain Error. withOtpHandling skips re-validation when the caught error is already an OtpRequiredError instance. https://claude.ai/code/session_0191GhgPWiD5TroLMoXAmkaZ * chore(git): revert an imperfect fix This reverts commit |
||
|
|
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> |
||
|
|
421ceac0b3 |
chore: compile pnpm CLI bundle before tests that use it (#11059)
Packages whose tests spawn the local pnpm CLI (pnpm/bin/pnpm.mjs) need the bundle (pnpm/dist/pnpm.mjs) to exist. Add `pnpm --filter pnpm run compile` to their test scripts so the bundle is built before tests run. |
||
|
|
41dc031a67 |
test: use resolution-mode=highest in tests (#10989)
* fix: configure default resolution-mode to highest in pkg-manager/core
* test: update catalog tests for resolution-mode=highest
* test: fix `--fix-lockfile` test for new resolution-mode default
```
● fix broken lockfile with --fix-lockfile
expect(received).toBeTruthy()
Received: undefined
55 | const lockfile: LockfileFile = readYamlFileSync(WANTED_LOCKFILE)
56 | expect(Object.keys(lockfile.packages as PackageSnapshots)).toHaveLength(2)
> 57 | expect(lockfile.packages?.['@types/semver@5.3.31']).toBeTruthy()
| ^
58 | expect(lockfile.packages?.['@types/semver@5.3.31']?.resolution).toEqual({
59 | integrity: 'sha512-WBv5F9HrWTyG800cB9M3veCVkFahqXN7KA7c3VUCYZm/xhNzzIFiXiq+rZmj75j7GvWelN3YNrLX7FjtqBvhMw==',
60 | })
at Object.<anonymous> (test/install/fixLockfile.ts:57:55)
```
* test: fix lockfile conflict test
● a lockfile v6 with merge conflicts is autofixed
expect(received).toHaveProperty(path, value)
Expected path: "version"
Expected value: "100.1.0"
Received value: "101.0.0"
1284 |
1285 | const lockfile = project.readLockfile()
> 1286 | expect(lockfile.importers?.['.'].dependencies?.['@pnpm.e2e/dep-of-pkg-with-1-dep']).toHaveProperty('version', '100.1.0')
| ^
1287 | })
1288 |
1289 | test('a lockfile with duplicate keys is fixed', async () => {
at Object.<anonymous> (test/lockfile.ts:1286:87)
* test: fix deploy shared lockfile test
● deploy with a shared lockfile that has peer dependencies suffix in workspace package dependency paths
expect(received).toMatchObject(expected)
- Expected - 6
+ Received + 1
@@ -1,11 +1,11 @@
Object {
"importers": Object {
"packages/project-0": Object {
"dependencies": Object {
"project-1": Object {
- "version": "file:packages/project-1(is-negative@1.0.0)(project-2@file:packages/project-2(is-positive@1.0.0))",
+ "version": "file:packages/project-1(is-negative@2.1.0)(project-2@file:packages/project-2(is-positive@1.0.0))",
},
"project-2": Object {
"version": "file:packages/project-2(is-positive@1.0.0)",
},
},
@@ -31,13 +31,8 @@
"type": "directory",
},
},
},
"snapshots": Object {
- "project-1@file:packages/project-1(is-negative@1.0.0)(project-2@file:packages/project-2(is-positive@1.0.0))": Object {
- "dependencies": Object {
- "project-2": "file:packages/project-2(is-positive@1.0.0)",
- },
- },
"project-2@file:packages/project-2(is-positive@1.0.0)": Object {},
},
}
950 | workspaceDir: process.cwd(),
951 | })
> 952 | expect(assertProject('.').readLockfile()).toMatchObject({
| ^
953 | importers: {
954 | 'packages/project-0': {
955 | dependencies: {
at Object.<anonymous> (test/shared-lockfile.test.ts:952:45)
* test: fix injectLocalPackages test
|
||
|
|
cd2dc7d481 |
refactor: prefix internal scripts with . to hide them (#11051)
* fix: ensure PNPM_HOME/bin is in PATH during pnpm setup When upgrading from old pnpm (global bin = PNPM_HOME) to new pnpm (global bin = PNPM_HOME/bin), `pnpm setup` would fail because the spawned `pnpm add -g` checks that the global bin dir is in PATH. Prepend PNPM_HOME/bin to PATH in the spawned process env so the check passes during the transition. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update pnpm to v11 beta 2 * chore: update pnpm to v11 beta 2 * chore: update pnpm to v11 beta 2 * chore: update pnpm to v11 beta 2 * fix: lint * refactor: rename _-prefixed scripts to .-prefixed scripts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update root package.json to use .test instead of _test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ci: update action-setup --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
812cae93d6 | test(releasing): fix | ||
|
|
1701a65845 |
chore: reduce noisy warnings in test output (#11022)
* chore: reduce noisy warnings in test output - Suppress ExperimentalWarning and DEP0169 via --disable-warning in NODE_OPTIONS - Fix MaxListenersExceededWarning by raising limit in StoreIndex when adding exit listeners - Update meta-updater to generate the new _test scripts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: stop streaming pnpm subprocess output during CLI tests Buffer stdout/stderr from execPnpm instead of writing to the parent process in real time. Output is still included in the error message on failure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: pipe all subprocess output in CLI tests Use stdio: 'pipe' for all pnpm/pnpx spawn helpers so subprocess output is buffered instead of printed. Output is still included in error messages on failure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove duplicate @pnpm/installing.env-installer in pnpm/package.json Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: use pipe stdio in dlx and errorHandler tests Replace stdio: 'inherit' and [null, 'pipe', 'inherit'] with 'pipe' to prevent subprocess output from leaking into test output. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: skip maxListeners adjustment when set to unlimited (0) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
303ca410f5 |
feat!: stop reading settings from the pnpm field of package.json (#10086)
Settings should be read from pnpm-workspace.yaml |
||
|
|
d0ae78821a |
refactor: rename workspace functions from packages to projects (#11002)
Align function, type, and file names with the packages-to-projects rename in workspace packages (projects-filter, projects-reader, projects-sorter). |
||
|
|
dba4153767 |
refactor: rename packages and consolidate runtime resolvers (#10999)
* refactor: rename workspace.sort-packages and workspace.pkgs-graph - workspace.sort-packages -> workspace.projects-sorter - workspace.pkgs-graph -> workspace.projects-graph Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: rename packages/ to core/ and pkg-manifest.read-package-json to reader - Rename packages/ directory to core/ for clarity - Rename pkg-manifest/read-package-json to pkg-manifest/reader (@pnpm/pkg-manifest.reader) - Update all tsconfig, package.json, and lockfile references Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: consolidate runtime resolvers under engine/runtime domain - Remove unused @pnpm/engine.runtime.node.fetcher package - Rename engine/runtime/node.resolver to node-resolver (dash convention) - Move resolving/bun-resolver to engine/runtime/bun-resolver - Move resolving/deno-resolver to engine/runtime/deno-resolver - Update all package names, tsconfig paths, and lockfile references Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: update lockfile after removing node.fetcher Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: sort tsconfig references and package.json deps alphabetically Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: auto-fix import sorting Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update __typings__ paths in tsconfig.lint.json for moved resolvers Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: remove deno-resolver from deps of bun-resolver --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
4a36b9a110 |
refactor: rename internal packages to @pnpm/<domain>.<leaf> convention (#10997)
## Summary Rename all internal packages so their npm names follow the `@pnpm/<domain>.<leaf>` convention, matching their directory structure. Also rename directories to remove redundancy and improve clarity. ### Bulk rename (94 packages) All `@pnpm/` packages now derive their name from their directory path using dot-separated segments. Exceptions: `packages/`, `__utils__/`, and `pnpm/artifacts/` keep leaf names only. ### Directory renames (removing redundant prefixes) - `cli/cli-meta` → `cli/meta`, `cli/cli-utils` → `cli/utils` - `config/config` → `config/reader`, `config/config-writer` → `config/writer` - `fetching/fetching-types` → `fetching/types` - `lockfile/lockfile-to-pnp` → `lockfile/to-pnp` - `store/store-connection-manager` → `store/connection-manager` - `store/store-controller-types` → `store/controller-types` - `store/store-path` → `store/path` ### Targeted renames (clarity improvements) - `deps/dependency-path` → `deps/path` (`@pnpm/deps.path`) - `deps/calc-dep-state` → `deps/graph-hasher` (`@pnpm/deps.graph-hasher`) - `deps/inspection/dependencies-hierarchy` → `deps/inspection/tree-builder` (`@pnpm/deps.inspection.tree-builder`) - `bins/link-bins` → `bins/linker`, `bins/remove-bins` → `bins/remover`, `bins/package-bins` → `bins/resolver` - `installing/get-context` → `installing/context` - `store/package-store` → `store/controller` - `pkg-manifest/manifest-utils` → `pkg-manifest/utils` ### Manifest reader/writer renames - `workspace/read-project-manifest` → `workspace/project-manifest-reader` (`@pnpm/workspace.project-manifest-reader`) - `workspace/write-project-manifest` → `workspace/project-manifest-writer` (`@pnpm/workspace.project-manifest-writer`) - `workspace/read-manifest` → `workspace/workspace-manifest-reader` (`@pnpm/workspace.workspace-manifest-reader`) - `workspace/manifest-writer` → `workspace/workspace-manifest-writer` (`@pnpm/workspace.workspace-manifest-writer`) ### Workspace package renames - `workspace/find-packages` → `workspace/projects-reader` - `workspace/find-workspace-dir` → `workspace/root-finder` - `workspace/resolve-workspace-range` → `workspace/range-resolver` - `workspace/filter-packages-from-dir` merged into `workspace/filter-workspace-packages` → `workspace/projects-filter` ### Domain moves - `pkg-manifest/read-project-manifest` → `workspace/project-manifest-reader` - `pkg-manifest/write-project-manifest` → `workspace/project-manifest-writer` - `pkg-manifest/exportable-manifest` → `releasing/exportable-manifest` ### Scope - 1206 files changed - Updated: package.json names/deps, TypeScript imports, tsconfig references, changeset files, renovate.json, test fixtures, import ordering |
||
|
|
7a304b17c4 |
refactor: rename directories and unify command packages per domain (#10993)
- Rename `installing/core` → `installing/deps-installer` and `installing/headless` → `installing/deps-restorer` for clearer naming
- Rename all `plugin-commands-*` directories to use `-commands` suffix convention
- Merge multiple command packages per domain into a single `commands/` directory (one commands package per domain rule):
- `building/{build-commands,policy-commands}` → `building/commands`
- `deps/compliance/{audit-commands,licenses-commands,sbom-commands}` → `deps/compliance/commands`
- `deps/inspection/{listing-commands,outdated-commands}` → `deps/inspection/commands`
- `store/{store-commands,inspecting-commands}` → `store/commands`
- `releasing/{publish-commands,deploy-commands}` → `releasing/commands`
- `cli/{completion-commands,doctor-commands}` → `cli/commands`
- `engine/pm/{self-updater-commands,setup-commands}` → `engine/pm/commands`
- `engine/runtime/{runtime-commands,env-commands}` → `engine/runtime/commands`
- `cache/cache-commands` → `cache/commands`
- Fix relative paths in merged test files (pnpmBin, __typings__ references)
- Update jest config to ignore `utils/` dirs at any nesting depth under `test/`
- Fix stale package names in changeset files
|