Skip to content

fix(migrate): tolerate nested npm overrides during bootstrap detection - #2267

Open
charpeni wants to merge 2 commits into
voidzero-dev:mainfrom
charpeni:fix/migrate-nested-npm-overrides
Open

fix(migrate): tolerate nested npm overrides during bootstrap detection#2267
charpeni wants to merge 2 commits into
voidzero-dev:mainfrom
charpeni:fix/migrate-nested-npm-overrides

Conversation

@charpeni

Copy link
Copy Markdown
Contributor

Summary

  • guard overrideSpecSatisfiesVitePlus so a non-string override value never reaches spec.startsWith(), which crashed vp migrate with TypeError: spec.startsWith is not a function
  • treat nested npm override objects (e.g. {"overrides": {"vite": {"rollup": "..."}}}) as not satisfying the managed override, so the bootstrap stays pending and ensureOverrideEntries writes the managed alias
  • add a regression test covering nested objects under both managed keys (vite and vitest)

Why

npm supports nested overrides objects (a user override scoped under a dependency), but detectVitePlusBootstrapPending assumed every override value is a string. A valid package.json with a nested override under a managed key crashed migration during bootstrap detection.

A nested object never aliases the dependency itself, so it cannot satisfy the managed Vite+ override. Returning false makes detection report the bootstrap as pending, and the existing rewrite then sets the managed spec — after which detection converges. The single guard covers every caller (overridesSatisfyVitePlus across npm/bun/pnpm/yarn sources, npmVitePlusManagedDependenciesPending, and ensureOverrideEntries), and also hardens against other non-string values, such as a numeric scalar read from pnpm-workspace.yaml overrides.

When the project does not use vitest directly, a user override scoped under vitest is left intact, matching the existing contract documented in removeManagedVitestEntry. Note that under a managed key the rewrite replaces the nested object with the managed string spec, dropping any user sub-overrides scoped beneath it (e.g. a vite > rollup pin); preserving those via npm's nested "." syntax is left as a possible follow-up.

Fixes #2002.

Validation

  • pnpm -F vite-plus exec vitest run src/migration/__tests__/migrator.spec.ts -t 'tolerates nested npm override objects' — fails without the fix with the exact reported crash (TypeError: spec.startsWith is not a function at overrideSpecSatisfiesVitePlus, reached via detectVitePlusBootstrapPending), passes with it
  • full src/migration/__tests__/migrator.spec.ts run — no changes to any existing test outcome
  • also exercised locally (not committed): nested objects under both keys with usesVitest = true (both rewritten to managed specs, detection converges) and a nested object in yarn resolutions (converges without crashing)
  • type check of packages/cli is clean

@netlify

netlify Bot commented Jul 27, 2026

Copy link
Copy Markdown

Deploy Preview for viteplus-preview canceled.

Name Link
🔨 Latest commit a9f1575
🔍 Latest deploy log https://app.netlify.com/projects/viteplus-preview/deploys/6a701459cbe5ac000784fa8f

@fengmk2 fengmk2 self-assigned this Aug 3, 2026
@fengmk2

fengmk2 commented Aug 3, 2026

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a9f15758d9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +130 to 131
if (typeof spec !== 'string' || !spec) {
return false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve nested override children when adding the managed alias

When overrides.vite uses npm's long object form, returning false here makes ensureOverrideEntries replace the entire object with a string, silently deleting child overrides such as the test's rollup pin. It also misclassifies { ".": "npm:@voidzero-dev/vite-plus-core@latest", "rollup": "^4" }, even though the managed alias is already satisfied. The npm 11.4.2 package-json documentation explicitly defines this form as supporting both the package itself via "." and its children, so migration should preserve the object and inspect or set its "." member rather than collapsing it.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(migrate): tolerate nested npm overrides during bootstrap detection

2 participants