Conversation
A named catalog whose name parses as a version (e.g. catalog:express4-21) had its range policy overridden by pnpm update because whichVersionIsPinned misread the catalog: reference in the previous specifier as a pinned version. The catalog reference carries no pinning of its own, so the prefix from the catalog entry is now preserved. Closes #10321
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthrough
ChangesCatalog version-range policy fix
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoFix pnpm update to preserve catalog version range policy WalkthroughsDescription• Prevent pnpm update from widening named catalog specifiers from ~ to ^ • Treat all catalog:* references as unpinned so catalog entry policy wins • Add unit + e2e regression coverage for version-like catalog names Diagramgraph TD
A["pnpm update"] --> B["deps-installer (mutateModules)"] --> C["whichVersionIsPinned()"] --> D{"spec starts with catalog:?"}
D -->|"yes"| E["return undefined"] --> F["preserve catalog prefix (~)"] --> G[("lockfile catalogs")]
D -->|"no"| H["semver-utils parseRange"] --> I["derive pin (major/minor/patch)"] --> G
subgraph Legend
direction LR
_proc["Process"] ~~~ _dec{"Decision"} ~~~ _db[("Data store")]
end
High-Level AssessmentThe following are alternative approaches to this PR: 1. Skip pin-detection earlier in the update pipeline
2. Tighten parsing logic to ignore non-semver tokens after protocol stripping
Recommendation: Current approach (early-return File ChangesBug fix (1)
Tests (2)
Documentation (1)
|
What
Fixes #10321:
pnpm updateoverriding the version range policy of a catalog entry.When a dependency points at a named catalog whose name parses as a version — e.g.
"express": "catalog:express4-21"referencing a catalog entryexpress: ~4.21.2— runningpnpm updatewidened the catalog entry's~range to^.Root cause
During update, the dependency's previous specifier is the catalog reference
catalog:express4-21.whichVersionIsPinnedstrips everything before the first colon, leavingexpress4-21, whichsemver-utils'parseRangeinterprets as a version with major4. It therefore returned'major'(=>^) and overrode the real catalog specifier's~pin.This only reproduced with named catalogs whose names look like versions;
catalog:(default) and non-numeric names likecatalog:fooparse to[]and were unaffected — which matches the reporter's "I could only reproduce this behavior in catalogs".Fix
A
catalog:reference carries no version pinning of its own — the pinning lives in the catalog entry, which is already substituted into the bare specifier before the prefix is computed.whichVersionIsPinnednow returnsundefinedfor anycatalog:spec, so the catalog entry's own prefix wins.Tests
whichVersionIsPinned.test.tsforcatalog:,catalog:default,catalog:foo, andcatalog:express4-21.deps-installer/test/catalogs.tsthat runspnpm updateover a version-like named catalog and asserts the~prefix is preserved. It fails onmain(~1.0.0→^1.0.0) and passes with the fix.pacquet parity
Not applicable: pacquet doesn't implement pin-preservation on update (it always writes
^unless--save-exact), so it doesn't share this code path. No pacquet-side change is needed for this fix.Written by an agent (Claude Code, claude-opus-4-8).
Summary by CodeRabbit
pnpm updateincorrectly overriding version-range policies for named catalogs with version-like names (e.g.,express4-21). Catalog pinning prefixes are now correctly preserved during installation and updates.