Skip to content

Commit 47cc4bb

Browse files
committed
docs: record the exact-prerelease gap in the pnpm override key
Codex review on 4321a19: `vite@*` does not match a declaration pinning an exact prerelease. pnpm compares with semver.intersects(declaredSpec, keyRange), which is asymmetric for prereleases: intersects('8.0.0-beta.18', '*') is false while the reverse is true. My earlier justification checked the wrong argument order. Verified on pnpm 11.20.0: a bare key redirects an exact-prerelease declaration, the ranged key does not. No range string avoids it, because node-semver only admits a prerelease when a comparator carries the same version tuple. A prerelease RANGE (^8.0.0-beta.1) still matches, and pnpm 12.0.0-rc.3 matches the exact form too, so the gap is pnpm 9-11 only. A bare key would close it but is what clobbers catalog:, so below pnpm 12 the two cannot both hold. Corrects the comments and guide text that claimed the range keeps the override on every valid semver range.
1 parent 4321a19 commit 47cc4bb

3 files changed

Lines changed: 27 additions & 12 deletions

File tree

docs/guide/migrate-rules.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,14 @@ Related rules:
8686
`vitest@*`). pnpm applies an override by replacing the declared spec on every
8787
manifest, importer manifests included. A bare key matches any spec, including
8888
`catalog:`, and `vp up` then rewrites that reference to a concrete version.
89-
The `@*` range keeps the override on the transitive and peer declarations it
90-
exists for. It leaves `catalog:` references to the catalog, which already
91-
resolves them to Vite+ core. Migration re-keys a project that still holds the
92-
bare key, and keeps its named-catalog choice.
89+
The `@*` range keeps the override on the semver ranges that transitive and
90+
peer declarations use. It leaves `catalog:` references to the catalog, which
91+
already resolves them to Vite+ core. Migration re-keys a project that still
92+
holds the bare key, and keeps its named-catalog choice.
93+
- On pnpm 9 to 11 that range does not match a declaration that pins an exact
94+
prerelease, such as `vite: "8.0.0-beta.18"`, so the override skips it and pnpm
95+
can install a separate upstream Vite. A prerelease range such as
96+
`^8.0.0-beta.1` still matches, and pnpm 12 matches the exact form as well.
9397
- The direct-entry rule above is pnpm-specific. Bun mirrors its core alias as
9498
a direct dependency for its peer resolver, and npm browser-provider layouts
9599
may need a top-level `vite` edge so nested Vitest packages can resolve

docs/guide/upgrade.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ If you migrated with `vp migrate`, your project pins `vitest` to an exact versio
7171
- **Yarn:** a `vitest` entry under `resolutions` in `package.json`
7272
- **pnpm:** a `vitest@*` entry under `overrides` in `pnpm-workspace.yaml` — unless your `package.json` already had a `pnpm` field, in which case it lives under `pnpm.overrides` in `package.json` instead (pnpm ignores `pnpm-workspace.yaml` overrides when `package.json` defines `pnpm.overrides`)
7373

74-
Under pnpm the managed keys use an explicit `@*` range (`vite@*`, `vitest@*`). pnpm applies an override by replacing the declared spec on every manifest, importer manifests included. A bare key matches any spec, including `catalog:`. The `@*` range keeps the override on the transitive and peer declarations it exists for, and leaves `catalog:` references intact. `vp up` therefore no longer rewrites them to a concrete version.
74+
Under pnpm the managed keys use an explicit `@*` range (`vite@*`, `vitest@*`). pnpm applies an override by replacing the declared spec on every manifest, importer manifests included. A bare key matches any spec, including `catalog:`. The `@*` range keeps the override on the semver ranges that transitive and peer declarations use, and leaves `catalog:` references intact. `vp up` therefore no longer rewrites them to a concrete version. On pnpm 9 to 11 the range does not match a declaration that pins an exact prerelease (`vite: "8.0.0-beta.18"`); a prerelease range such as `^8.0.0-beta.1` still matches, and pnpm 12 matches both.
7575

7676
A Vite+ release can bump the bundled Vitest. Because that pin also applies to `vite-plus`'s own `vitest` dependency, an out-of-date pin keeps installing the previous runner even after you upgrade `vite-plus` — splitting Vitest's internals (mocks, `expect`, runner state) between the pinned copy and the one `vp test` loads.
7777

packages/cli/src/migration/migrator/shared.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -173,13 +173,24 @@ export const LEGACY_WRAPPER_FALLBACK_VERSIONS: Record<string, string> = {
173173
* catalog during resolution, and `pnpm update` then writes the resolved core
174174
* alias into that importer's package.json (issue #2309).
175175
*
176-
* The `@*` range keeps the override on every valid semver range. Transitive and
177-
* peer `vite` declarations always use such a range, and they are the reason this
178-
* override exists. The range also leaves `catalog:` specs alone, because `*` is
179-
* a valid semver range and `catalog:` is not, so pnpm's `isIntersectingRange`
180-
* never matches the two. The installed result does not change: an importer that
181-
* references the catalog already resolves to the aliased core through its
182-
* catalog entry.
176+
* The `@*` range keeps the override on the declared semver ranges that
177+
* transitive and peer `vite` declarations use, and those declarations are the
178+
* reason this override exists. The range leaves `catalog:` specs alone, because
179+
* `catalog:` is not a valid semver range, so pnpm's `isIntersectingRange`
180+
* rejects it before it compares anything. The installed result does not change:
181+
* an importer that references the catalog already resolves to the aliased core
182+
* through its catalog entry.
183+
*
184+
* KNOWN GAP on pnpm 9 to 11. A declaration that pins an EXACT prerelease, such
185+
* as `vite: "8.0.0-beta.18"`, escapes the override. pnpm compares with
186+
* `semver.intersects(declaredSpec, keyRange)`, and that call is asymmetric for
187+
* prereleases: it returns false for an exact prerelease against a wildcard
188+
* range, even though the arguments in the other order return true. No range
189+
* string avoids this, because node-semver only admits a prerelease when a
190+
* comparator carries the same version tuple. A prerelease RANGE such as
191+
* `^8.0.0-beta.1` still matches, and pnpm 12 matches the exact form too. A bare
192+
* key would cover this case, but a bare key is what clobbers `catalog:`, so
193+
* below pnpm 12 the two cannot both hold.
183194
*
184195
* This applies to pnpm only. npm and bun `overrides`, and yarn `resolutions`,
185196
* keep bare keys. Those package managers have no `catalog:` importer specs to

0 commit comments

Comments
 (0)