* chore(release): 11.28.7, pacquet 12.15.0, pnpr 0.1.0-alpha.16
* docs(release): curate 11.28.7, pacquet 12.15.0, and pnpr 0.1.0-alpha.16 release notes
Add lead paragraphs and group the patch entries by what the reader was
doing, with security fixes first on each page.
- v11: lead with the registry metadata name check, pinned pnpm
trustPolicy check, maxTarballUnpackedSize, and the removal of registry
revisions; merge overlapping entries for minimumReleaseAge metadata
revalidation, frozen-lockfile directory dependency checks,
syncInjectedDepsAfterScripts, verifyDepsBeforeRun, pnpm sbom, and
unreadable config settings.
- v12: order minor highlights from config includes and
lockfile.integrityTarget down to interactive update styling; drop the
pnpr-only distribution note from the CLI changelog; merge overlapping
entries for workspace and pnpr install speedups, minimumReleaseAge and
If-Modified-Since revalidation, frozen-lockfile and injected package
checks, verifyDepsBeforeRun, pnpm prune, pnpm pack, pnpm licenses
list, pnpm self-update, pinned pnpm flag forwarding, and WebContainer
fixes.
- pnpr: lead the minor section with the breaking ecosystem URL prefix,
hosted storage layout, artifacts.orgs, and strict config schema
changes; fold dist.pnpr tarball metadata into one entry and drop the
redundant /metrics note; lead the patch section with reserved-username
and auth security fixes.
- Use one issue-link label style across the release pages.
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
* chore(release): 11.28.6, pacquet 12.14.0
* docs(release): curate 11.28.6 and pacquet 12.14.0 release notes
Add lead paragraphs and group the patch entries by what the reader was
doing, with security first on the v11 page.
- v11: lead with the NPM_ID_TOKEN audience check and the invalid file
name warning as security fixes; say the `pnpm setup` message was
printed, since v11 reports it as a warning.
- v12: merge the stdout and stderr broken-pipe entries and the two
optional-peer entries; say the Windows Rust toolchain change undoes
the MinGW fallback a MinGW-built pnpm used since 12.13.0; correct the
`browser` packing claim; drop the reference to another release line.
- Use one issue-link label style on both pages.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(release): smooth two sentences in the 11.28.6 and 12.14.0 notes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(release): say sideEffectsCache.exclude covers the local and remote cache
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs: give sideEffectsCache.exclude an example a cache key cannot cover
An environment variable such as JAVA_HOME could be added to the cache
key, so it does not justify excluding a package. Name the system
libraries a native addon links against instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Prune explicit whole-subtree workspace exclusions during discovery in both
CLIs. Retain manifest filtering for membership, including parent-relative
negatives and directory-only exclusions. Rebase ancestor walks without lossy
path conversion.
Closespnpm/tasks#120.
---------
Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* chore(release): 11.28.5, pacquet 12.10.0
* docs(release): curate the 11.28.5 and 12.10.0 release notes
Add a lead paragraph to each page and group the patch entries under
subject headings, with the security fixes first.
- Merge the unpublish path-boundary fix into the unpublish entry, the
legacy metadata cache prune into the metadata cache entry, the two
binary size entries, and the two 64 MiB archive limits on the v11 page.
- Drop the manifest-utils saveType entry from the CLI page: the CLI
only passes saveType values derived from its own flags, so no CLI user
can reach the fixed path.
- Rewrite mechanism-only entries (PAX header validation, bundled
dependency symlinks, custom resolutions under name@version keys, proxy
setting validation) in terms of what the user sees.
- Use one link style for pnpm/pnpm issues.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The non-root warning for a "resolutions" field told users to configure
"resolutions" at the workspace root, but version overrides are wired
through the "overrides" field in pnpm-workspace.yaml. Restructure
uselessNonRootManifestFields into a map of field to suggestion so each
field carries its own remediation message.
Fixespnpm/pnpm#11757
Co-authored-by: shiminshen <16914659+shiminshen@users.noreply.github.com>
* chore(release): 11.28.4, pacquet 12.9.1
* docs(release): curate 11.28.4 and pacquet 12.9.1 release notes
Add a lead paragraph to both pages. Move the two credential-leak fixes
in 11.28.4 to the top and group the remaining 27 entries by what the
reader was doing. Merge entries that described one change: the two
INVALID_SETTING validations, the two metadata revalidation fixes, the
two hoisted filtered-install fixes, and, in pacquet 12.9.1, the two
[<since>] selector fixes. Order pacquet 12.9.1 so the `@pnpm/wasm` move,
which WebContainer users must act on, comes first.
Normalize issue links to the [#N] form and link the ETag fix to
pnpm/pnpm#16506.
Every fix was checked against the code released in 11.28.3 and
pacquet 12.9.0; none fixes a defect that never shipped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(release): describe the frozen-lockfile fixes accurately in the 11.28.4 lead
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* refactor(ts): meet size and shape limits in 5 packages
Meet size and shape limits in modules-yaml, projects-reader,
property-path, path-extender-posix, and workspace/commands.
Graduate them from PENDING_SIZE_AND_SHAPE_REFACTOR.
* refactor(ts): meet size and shape limits in 5 more packages
Meet size and shape limits in text/comments-parser,
text/tree-renderer, yaml/document-sync,
workspace/workspace-manifest-reader, and
workspace/injected-deps-syncer.
Graduate them from PENDING_SIZE_AND_SHAPE_REFACTOR.
Add TypeScript ports of the perfectionist rules that the Rust workspace
enforces through dylint.toml to @pnpm/eslint-config, with the same limits,
and fix every finding that needs no refactor.
The size and shape rules (function length, cognitive complexity, nesting,
local bindings, file length) are enforced for packages that already meet
them. The packages that do not are listed in PENDING_SIZE_AND_SHAPE_REFACTOR
in eslint.config.mjs and are refactored in follow-up changes.
The custom rules mirror perfectionist's semantics rather than reusing
sonarjs or max-lines-per-function, so that one limit means the same thing
in both codebases: a closure is a level of the body that contains it, a
nested function declaration is measured on its own, and a test-framework
callback plays the role of a #[test] function.
Bugs found and fixed along the way:
- a registry error body cut at exactly 64 KiB lost its truncation marker
- removing a dependency could leave dangling .bin shims
- constructor/__proto__ names crashed the projects graph, were skipped by
the injected-deps syncer, and were dropped from writeWantedLockfile's
returned lockfile
The CI chunk runner learns to run the node:test suite of the ESLint
config package.
* chore(release): 11.28.1, pacquet 12.8.0, pnpr 0.1.0-alpha.14
* docs(release): park Rust changelogs and curate release notes
The release bump ran with pnpm 12.7.0, which since pnpm/pnpm#14934
writes the changelog of every private project to a committed
CHANGELOG.md. pacquet, `@pnpm/napi` and `@pnpm/pnpr` are private
in-repo but published, and release.yml and the publish-time changelog
composer both read their parked section. Move the three sections back
to .changeset/changelogs so the GitHub release bodies and the npm
tarball changelogs are not empty. The tooling follow-up is recorded
on pnpm/tasks#38.
Curate the pnpm 11.28.1, pnpm 12.8.0 and pnpr 0.1.0-alpha.14 pages:
add lead paragraphs, group patch entries by subject, merge entries
describing one change, drop internals no CLI user sees, and fix
"instead of" tails, implementation names and link placement. This
addresses both Qodo findings on the catalog entry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
StackBlitz WebContainers reject asynchronous fs calls with errors that
inherit from Error but were not created by the native constructor, so
util.types.isNativeError() returns false for them. pnpm used that check
to recognize ENOENT and other codes, so a missing pnpm-lock.yaml was
rethrown and pnpm install failed on any project without a lockfile.
Add isError() to @pnpm/error, which accepts a native error or any
instanceof Error, and use it at every non-test call site. The native
check alone is still needed for Jest, where errors from another realm
fail instanceof. Update the AGENTS.md guidance to match.
Closespnpm/pnpm#15649
* chore(release): 11.28.0, pacquet 12.7.0, pnpr 0.1.0-alpha.13
* docs(release): curate the 11.28.0 and 12.7.0 release pages
Group both pages under subject headings with a lead paragraph that
names the headline changes and the security fixes, and move the
security entries to the top of the patch section.
Merge entries that describe one change: the node shim version files,
ranged selectors without a package.json, SemVer build metadata,
completion injection, custom modulesDir command lookup,
list --only-projects, store status, npm_execpath, catalog and npm-alias
workspace edges, the macOS CA fallback, and the prepare/devPreinstall
skips.
Drop entries that describe no change a published version could show:
the test-only --no-optional entry on both pages, the exported
CreateNewStoreControllerOptions type, the publish availability-probe
fix for a flag first shipping in 12.7.0, and the executable-bit check
the Rust CLI never had wrong.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(release): describe the bin shim part of the modulesDir entry accurately
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Workspace project discovery ignored `**/node_modules/**` but not the
configured `modulesDir`. An install creates `<project>/<modulesDir>` in
every project, and tinyglobby follows its symlinks into the virtual
store. With `modulesDir: vendor` and `packages: ['**']`, a repeat install
listed each dependency as a workspace project and ran its lifecycle
scripts outside the `allowBuilds` approval gate.
`findWorkspaceProjects` and the no-check variants take `modulesDir` and
add a `**/<modulesDir>/**` ignore for a path below the project. The CLI
entry, `pnpm clean`, and the deps-status fallback pass it. Commands that
spread their config into the options already carry it.
The first walk skips every directory named like a modules directory, so
it never enters a dependency. A second walk skips only
`<project>/<modulesDir>` for the projects found, and keeps the new
projects that are not inside the modules directory of a found project.
Walks repeat while they add projects. The result only grows, so the loop
terminates. A workspace with the default `node_modules` still takes a
single walk.
`packageConfigs` overrides are passed too, as `modulesDirsByProjectName`,
each applied only to its own project. The config reader derives that map,
so commands that spread their config into the discovery options carry it
like `modulesDir`. And
an absolute `modulesDir` inside the workspace is skipped with a pattern
anchored at the workspace root.
pnpm v12 is not affected: its walk does not follow directory symlinks,
and pnpm writes only symlinks into a project's modules directory.
Wildcards in negated workspace `packages` patterns now match dot
directories in both the workspace walk and the workspace-membership check,
matching pnpm v12.
---------
Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Restore JSON5 support through the shared project manifest reader and writer.
Use the existing JSON, JSON5, YAML precedence and select one manifest per
workspace directory in both implementations.
Pin json5 1.3.1. Bound deserialization to 128 levels before descending into
nested values, including unknown fields. Reject non-finite numbers instead
of silently converting them to null. Preserve comments with relocation
markers and verify semantic equality before atomic writes. Comment placement
is heuristic; exact lexical formatting is not preserved after an edit.
Use the same selection for project metadata commands, lifecycle hooks, publishing, versioning, root
override references, and dedicated-lockfile root detection. Ensure packing
contains exactly one normalized package.json even when files or .npmignore
exclude the source manifest. Keep dependency package.json readers strict.
Related to pnpm/pnpm#15129 and pnpm/pnpm#3027. Credit Simon Kagedal Reimer's
discovery analysis in pnpm/pnpm#11372; no preference setting is introduced.
---------
Co-authored-by: Zoltan Kochan <z@kochan.io>
Synchronous versions of workspace finder utilities were requested for tools and plugins that execute synchronously. This exports findWorkspaceDirSync, findPackagesSync, findWorkspaceProjectsSync, findWorkspaceProjectsNoCheckSync, readWorkspaceManifestSync, and readExactProjectManifestSync from the published workspace packages.
Closes#3000
`pnpm install` in a directory that the `packages` patterns do not select
installed every project in the workspace and left that directory untouched.
A directory that carries a manifest of its own and that no pattern selects is
a standalone project, so the workspace search now stops there, the way
`--ignore-workspace` makes it stop.
A directory without a manifest of its own, such as a package's source
directory, is not such a project: a command run from there still acts on the
workspace. So does the workspace root, which is a project whether or not a
pattern names it.
The membership question is answered with the patterns the project walk
expands, so a directory called a member is a directory the walk returns.
`@pnpm/workspace.package-patterns` now owns that expansion for the TypeScript
CLI and `findPackages` reads it from there; `pnpm_workspace::belongs_to_workspace`
owns it for pacquet, where both the workspace lookup and the configuration's
workspace layer ask it. `needs_package_patterns` names the cheap half of the
question — a directory below the workspace root carrying a manifest of its own
— so the workspace lookup reads `pnpm-workspace.yaml` only where the answer
turns on `packages:`, and a command run from the workspace root pays nothing.
Two tests described a project the workspace leaves out and relied on the old
behavior. The TypeScript one listed a pattern matching no directory it
prepares and now lists the project it creates; the pacquet one now asserts the
standalone install.
Closespnpm/pnpm#3561
Workspace discovery passed directory patterns to wax without the POSIX path
normalization that pnpm11 receives from tinyglobby. This could omit projects
from installs and recursive commands, or include projects a negation excluded.
Add a POSIX normalization entry point to pnpm-fs, sharing the existing dot and
parent-component reduction with native-path normalization. POSIX separators
are interpreted consistently on every platform, preserving glob backslashes.
Normalize each configured pattern before selecting the existing literal,
one-level wildcard, or generic glob discovery path. Preserve the original
pattern in invalid-glob diagnostics.
The TypeScript implementation already normalizes these paths through
tinyglobby. Add matching TypeScript regression coverage alongside Rust
filesystem/discovery tests and a CLI install/list/recursive-script test.
Fixespnpm/pnpm#14571.
---------
Co-authored-by: Zoltan Kochan <z@kochan.io>
Both utilities lived in the pnpm/components Bit workspace, where their
component names collide with same-named components elsewhere in the Bit
registry. Move the code here and publish it under new names:
`@pnpm/util.lex-comparator` -> `@pnpm/text.ordinal-comparator`
`@pnpm/config.nerf-dart` -> `@pnpm/config.registry-auth-key`
The new names describe what the utilities do: the comparator is ordinal
rather than locale-aware, and the mapped URL is the key that registry
settings are stored under in `.npmrc`. The exported functions keep their
names, so consumers only change their import specifiers.
Implementations and tests are carried over unchanged. The rationale from
the components' docs pages moves into doc comments: why `localeCompare`
cannot be used for values compared across machines, and where `nerfDart`
originates.
No pacquet counterpart is needed. The Rust stack has its own
implementations of both and no user-visible behavior changes.
Remove the legacy repository changelog files now that release changelog storage defaults to the registry. The publish path composes and injects CHANGELOG.md into release tarballs, so keeping historical copies in source control duplicates generated release data.
Update adm-zip to the patched 0.6 release and override vulnerable transitive versions after the dependency audit began rejecting versions below 0.6.0.
The TypeScript pnpm CLI freezes at v11; pnpm 12 will be the Rust pacquet
port. To make that split legible, all TypeScript source, test, and build
directories move under a new top-level pnpm11/ directory. The name states
the version boundary rather than implying a behavioral fork, since the two
stacks are meant to behave identically.
Scope is source-only: the shared workspace root stays at the repo root.
pnpm-workspace.yaml, package.json, pnpm-lock.yaml, .pnpmfile.cjs,
.meta-updater, __patches__, .changeset, .husky, and the lint/spell configs
remain in place, so one pnpm workspace and one Cargo workspace still span
all three products. pnpr/client and pacquet/tasks/registry-mock stay as
cross-product workspace members.
Rewiring the move required:
- pnpm-workspace.yaml globs prefixed with pnpm11/
- root package.json script paths, eslint.config.mjs, tsconfig.lint.json,
.gitignore, and CODEOWNERS updated
- .meta-updater/src/index.ts literals repointed (pnpm11/pnpm/package.json,
pnpm11/__utils__, pnpm11/__typings__, and the main package directory)
- regenerated every moved package's repository/homepage URL via meta-updater
- pnpm11/pnpm/bundle-deps.ts and __utils__/scripts/src/typecheck-only.ts
climb one more level to reach the repo root
.meta-updater stays at the repo root because @pnpm/meta-updater resolves
its config at <cwd>/.meta-updater/main.mjs.
TS CI (.github/workflows/ci.yml) now only runs when pnpm11/-relevant paths
change, via a dorny/paths-filter changes job plus a TS CI / Success
aggregate gate; branch protection should require only that gate.