From ff44fc156745eb60a6189097d1854eba46692009 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 15 May 2026 18:07:31 +0800 Subject: [PATCH 01/37] refactor: replace @voidzero-dev/vite-plus-test with upstream vitest@4.1.5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Delete the bundled `@voidzero-dev/vite-plus-test` wrapper and consume upstream `vitest@4.1.5` (plus `@vitest/browser*`) directly. The vite redirection that the wrapper used to provide is now handled cleanly by package-manager overrides (`vite` -> `@voidzero-dev/vite-plus-core`), so the bundle was dead weight that lagged upstream vitest releases. Public API contract preserved: - `vite-plus/test*` IS the public test API. Existing vite-plus user code (e.g. `import { vi } from 'vite-plus/test'`) is NEVER rewritten — the imports stay exactly as authored. - New vite-plus users do NOT install `vitest` or `@vitest/*` directly. They install `vite-plus`; vitest and the browser providers come in transitively as direct deps of the CLI package. - `vp migrate` on an upstream-vitest project still rewrites bare `vitest`, `vitest/*`, `@vitest/browser*`, declare-module specifiers and `/// ` directives to the `vite-plus/test*` surface (one-time forward migration). Implementation: - packages/cli/build.ts `syncTestPackageExports` auto-generates `./test/*` shims from `vitest`'s own exports map, plus `./test/` and `./test/browser/providers/` shims projected from each `@vitest/browser-*` package's exports. - packages/cli/package.json adds `@vitest/browser`, `@vitest/browser-playwright`, `@vitest/browser-preview`, `@vitest/browser-webdriverio` as direct catalog deps pinned to 4.1.5 alongside `vitest`. - crates/vite_global_cli/src/commands/version.rs version ToolSpec points at the `vitest` package directly. - packages/cli/src/resolve-test.ts resolves `vitest/package.json` and reads `bin.vitest` so `vp test` invokes upstream vitest. - packages/cli/src/utils/constants.ts drops `vitest` from `VITE_PLUS_OVERRIDE_PACKAGES`; only `vite` remains a managed key. - packages/cli/src/migration/migrator.ts adds an `isVitestAdjacent` flag that flips `needVitePlus = true` for projects with packages like `vitest-browser-svelte` even when no vite/oxlint/tsdown dep is being migrated; adds a `pruneLegacyWrapperAliases` / `pruneYamlMapLegacyWrapperAliases` sweep that rewrites stale `vitest: npm:@voidzero-dev/vite-plus-test@*` aliases to `^4.1.5` in package.json overrides/resolutions/pnpm.overrides, in pnpm-workspace.yaml catalog/catalogs/overrides, and in bun workspaces.catalog / workspaces.catalogs. - packages/cli/src/migration/bin.ts adds a `handleInstallResult` helper so failed reinstalls warn the user, append to `report.warnings`, and flip `process.exitCode` instead of being silently reported as success. Verification: - cargo test -p vite_migration --lib: 167 tests pass - pnpm exec vitest run (packages/cli): 355 tests pass - pnpm bootstrap-cli + snap-test-global + snap-test-local: all fixtures regenerated; expected diffs only (forward import rewrites, `@vitest/browser*` removed from user devDeps, `playwright`/`webdriverio` preserved as peers, stale `vite-plus-test` catalog aliases normalized to `^4.1.5`). Co-Authored-By: Claude Opus 4.7 --- .github/scripts/upgrade-deps.ts | 40 +- .github/workflows/e2e-test.yml | 1 - .github/workflows/prepare_release.yml | 1 - .github/workflows/publish-to-pkg.pr.new.yml | 3 +- .github/workflows/release.yml | 3 - .github/workflows/test-vp-create.yml | 3 +- README.md | 9 +- .../vite_global_cli/src/commands/version.rs | 6 +- crates/vite_migration/src/file_walker.rs | 11 +- docs/guide/migrate.md | 24 +- docs/guide/upgrade.md | 9 +- ecosystem-ci/patch-project.ts | 2 - justfile | 1 - packages/cli/BUNDLING.md | 59 +- packages/cli/README.md | 9 +- packages/cli/build.ts | 162 +- packages/cli/package.json | 172 +- packages/cli/publish-native-addons.ts | 6 - .../migration-add-git-hooks/snap.txt | 4 - .../snap.txt | 4 - .../migration-baseurl-tsconfig/snap.txt | 4 - .../snap.txt | 4 - .../snap.txt | 4 - .../migration-composed-husky-prepare/snap.txt | 4 - .../migration-env-prefix-lint-staged/snap.txt | 4 - .../migration-eslint-lint-staged/snap.txt | 4 - .../migration-eslint-lintstagedrc/snap.txt | 4 - .../migration-eslint-npx-wrapper/snap.txt | 4 - .../migration-eslint/snap.txt | 4 - .../snap.txt | 4 - .../snap.txt | 4 - .../snap.txt | 4 - .../migration-existing-husky/snap.txt | 4 - .../snap.txt | 4 - .../snap.txt | 4 - .../snap.txt | 4 - .../snap.txt | 4 - .../migration-from-tsdown/snap.txt | 4 - .../migration-from-vitest-config/snap.txt | 6 +- .../migration-from-vitest-files/snap.txt | 6 +- .../snap.txt | 4 - .../snap.txt | 4 - .../migration-husky-latest-dist-tag/snap.txt | 4 - .../migration-husky-or-prepare/snap.txt | 4 - .../snap.txt | 4 - .../snap.txt | 4 - .../migration-lint-staged-in-scripts/snap.txt | 4 - .../migration-lint-staged-merge-fail/snap.txt | 4 - .../migration-lint-staged-ts-config/snap.txt | 4 - .../migration-lintstagedrc-json/snap.txt | 4 - .../snap.txt | 4 - .../snap.txt | 4 - .../snap.txt | 4 - .../migration-merge-vite-config-js/snap.txt | 4 - .../migration-merge-vite-config-ts/snap.txt | 6 +- .../migration-monorepo-bun/snap.txt | 5 +- .../snap.txt | 4 - .../migration-monorepo-pnpm/snap.txt | 6 +- .../migration-monorepo-yarn4/snap.txt | 4 +- .../migration-no-git-repo/snap.txt | 4 - .../migration-no-hooks-with-husky/snap.txt | 4 - .../migration-no-hooks/snap.txt | 4 - .../migration-other-hook-tool/snap.txt | 4 - .../snap.txt | 4 - .../migration-oxlintrc-jsonc/snap.txt | 4 - .../snap.txt | 4 - .../migration-prettier-eslint-combo/snap.txt | 4 - .../snap.txt | 4 - .../migration-prettier-lint-staged/snap.txt | 4 - .../migration-prettier-pkg-json/snap.txt | 4 - .../migration-prettier/snap.txt | 4 - .../migration-rewrite-declare-module/snap.txt | 4 - .../migration-skip-vite-dependency/snap.txt | 4 - .../snap.txt | 4 - .../migration-standalone-npm/snap.txt | 5 +- .../migration-standalone-pnpm/snap.txt | 6 +- .../migration-subpath/snap.txt | 4 - .../snap.txt | 4 - .../migration-vite-version/snap.txt | 4 - .../migration-vitest-peer-dep/snap.txt | 4 - .../new-vite-monorepo-bun/snap.txt | 4 +- .../new-vite-monorepo/snap.txt | 4 - .../cli/snap-tests/command-helper/snap.txt | 24 +- .../create-org-bundled-monorepo/snap.txt | 4 - .../test-inline-snapshot-indent/snap.txt | 3 +- .../vite-plugins-async-test/snap.txt | 3 +- .../vite-plugins-async-test/src/index.test.ts | 2 +- .../cli/src/__tests__/exports-map.spec.ts | 88 + packages/cli/src/__tests__/index.spec.ts | 2 +- packages/cli/src/__tests__/pack.spec.ts | 2 +- .../cli/src/__tests__/resolve-lint.spec.ts | 2 +- packages/cli/src/__tests__/versions.spec.ts | 17 +- packages/cli/src/define-config.ts | 5 +- packages/cli/src/index.cts | 2 +- packages/cli/src/index.ts | 2 +- .../bun-catalog-file-protocol.spec.ts | 10 +- .../__tests__/install-failure-guard.spec.ts | 77 + .../src/migration/__tests__/migrator.spec.ts | 59 +- packages/cli/src/migration/bin.ts | 46 +- packages/cli/src/migration/migrator.ts | 127 +- packages/cli/src/resolve-test.ts | 23 +- packages/cli/src/utils/constants.ts | 1 - packages/test/.gitignore | 8 - packages/test/BUNDLING.md | 427 --- .../test/__tests__/build-artifacts.spec.ts | 115 - packages/test/build.ts | 2649 ----------------- packages/test/package.json | 368 --- packages/test/tsconfig.json | 9 - packages/tools/package.json | 2 +- packages/tools/src/__tests__/utils.spec.ts | 2 +- pnpm-lock.yaml | 1445 ++------- pnpm-workspace.yaml | 11 +- rfcs/cli-output-polish.md | 4 +- rfcs/migration-command.md | 34 +- vite.config.ts | 7 - 115 files changed, 900 insertions(+), 5469 deletions(-) create mode 100644 packages/cli/src/__tests__/exports-map.spec.ts create mode 100644 packages/cli/src/migration/__tests__/install-failure-guard.spec.ts delete mode 100644 packages/test/.gitignore delete mode 100644 packages/test/BUNDLING.md delete mode 100644 packages/test/__tests__/build-artifacts.spec.ts delete mode 100644 packages/test/build.ts delete mode 100644 packages/test/package.json delete mode 100644 packages/test/tsconfig.json diff --git a/.github/scripts/upgrade-deps.ts b/.github/scripts/upgrade-deps.ts index 3f7d4ac1ad..bc478f4914 100644 --- a/.github/scripts/upgrade-deps.ts +++ b/.github/scripts/upgrade-deps.ts @@ -155,8 +155,13 @@ async function updatePnpmWorkspace(versions: PnpmWorkspaceVersions): Promise { - const filePath = path.join(ROOT, 'packages/test/package.json'); - const pkg: PackageJson = readJsonFile(filePath); - const devDependencies = pkg.devDependencies; - if (!devDependencies) { - throw new Error('packages/test/package.json is missing devDependencies'); - } - - // Update all @vitest/* devDependencies - for (const dep of Object.keys(devDependencies)) { - if (dep.startsWith('@vitest/')) { - devDependencies[dep] = vitestVersion; - } - } - - // Update vitest-dev devDependency - if (devDependencies['vitest-dev']) { - devDependencies['vitest-dev'] = `^${vitestVersion}`; - } - - // Update @vitest/ui peerDependency if present - if (pkg.peerDependencies?.['@vitest/ui']) { - pkg.peerDependencies['@vitest/ui'] = vitestVersion; - } - - fs.writeFileSync(filePath, JSON.stringify(pkg, null, 2) + '\n'); - console.log('Updated packages/test/package.json'); -} - // ============ Update packages/core/package.json ============ async function updateCorePackage(devtoolsVersion: string): Promise { const filePath = path.join(ROOT, 'packages/core/package.json'); @@ -430,7 +405,6 @@ await updatePnpmWorkspace({ oxcParser: oxcParserVersion, oxcTransform: oxcTransformVersion, }); -await updateTestPackage(vitestVersion); await updateCorePackage(devtoolsVersion); writeMetaFiles(); diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 03c3830ca3..6b7fec6924 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -109,7 +109,6 @@ jobs: run: | mkdir -p tmp/tgz cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. - cd packages/test && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. # Copy vp binary for e2e-test job (findVpBinary expects it in target/) cp target/${{ matrix.target }}/release/vp tmp/tgz/vp 2>/dev/null || cp target/${{ matrix.target }}/release/vp.exe tmp/tgz/vp.exe 2>/dev/null || true diff --git a/.github/workflows/prepare_release.yml b/.github/workflows/prepare_release.yml index a12f0987e2..59b722b05a 100644 --- a/.github/workflows/prepare_release.yml +++ b/.github/workflows/prepare_release.yml @@ -54,7 +54,6 @@ jobs: } update_json packages/cli/package.json update_json packages/core/package.json - update_json packages/test/package.json update_toml packages/cli/binding/Cargo.toml update_toml crates/vite_global_cli/Cargo.toml diff --git a/.github/workflows/publish-to-pkg.pr.new.yml b/.github/workflows/publish-to-pkg.pr.new.yml index b75317c9aa..620c9170b5 100644 --- a/.github/workflows/publish-to-pkg.pr.new.yml +++ b/.github/workflows/publish-to-pkg.pr.new.yml @@ -136,5 +136,4 @@ jobs: './packages/cli/cli-npm/*' \ './packages/cli' \ './packages/core' \ - './packages/prompts' \ - './packages/test' + './packages/prompts' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1cf037db85..cdbcf45e06 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -157,7 +157,6 @@ jobs: - name: Publish run: | pnpm publish --filter=./packages/core --tag latest --access public --no-git-checks - pnpm publish --filter=./packages/test --tag latest --access public --no-git-checks pnpm publish --filter=./packages/cli --tag latest --access public --no-git-checks - name: Create release body @@ -173,7 +172,6 @@ jobs: ### Published Packages - \`@voidzero-dev/vite-plus-core@${VERSION}\` - - \`@voidzero-dev/vite-plus-test@${VERSION}\` - \`vite-plus@${VERSION}\` ### Installation @@ -222,7 +220,6 @@ jobs: **Published Packages:** • @voidzero-dev/vite-plus-core@${{ env.VERSION }} - • @voidzero-dev/vite-plus-test@${{ env.VERSION }} • vite-plus@${{ env.VERSION }} **Install:** diff --git a/.github/workflows/test-vp-create.yml b/.github/workflows/test-vp-create.yml index 50fe50e4e0..6c9d5ec23c 100644 --- a/.github/workflows/test-vp-create.yml +++ b/.github/workflows/test-vp-create.yml @@ -94,7 +94,6 @@ jobs: run: | mkdir -p tmp/tgz cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. - cd packages/test && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. # Copy vp binary for test jobs cp target/x86_64-unknown-linux-gnu/release/vp tmp/tgz/vp @@ -152,7 +151,7 @@ jobs: - yarn - bun env: - VP_OVERRIDE_PACKAGES: '{"vite":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz","vitest":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-test-0.0.0.tgz","@voidzero-dev/vite-plus-core":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz","@voidzero-dev/vite-plus-test":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-test-0.0.0.tgz"}' + VP_OVERRIDE_PACKAGES: '{"vite":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz","@voidzero-dev/vite-plus-core":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz"}' VP_VERSION: 'file:${{ github.workspace }}/tmp/tgz/vite-plus-0.0.0.tgz' # Force full dependency rewriting so the library template's existing # vite-plus dep gets overridden with the local tgz diff --git a/README.md b/README.md index e9019fc152..c31da0cb13 100644 --- a/README.md +++ b/README.md @@ -189,12 +189,11 @@ If you are manually migrating a project to Vite+, install these dev dependencies npm install -D vite-plus @voidzero-dev/vite-plus-core@latest ``` -You need to add overrides to your package manager for `vite` and `vitest` so that other packages depending on Vite and Vitest will use the Vite+ versions: +You need to add overrides to your package manager for `vite` so that other packages depending on Vite (including Vitest) will use the Vite+ version: ```json "overrides": { - "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest" + "vite": "npm:@voidzero-dev/vite-plus-core@latest" } ``` @@ -203,15 +202,13 @@ If you are using `pnpm`, add this to your `pnpm-workspace.yaml`: ```yaml overrides: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest ``` Or, if you are using Yarn: ```json "resolutions": { - "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest" + "vite": "npm:@voidzero-dev/vite-plus-core@latest" } ``` diff --git a/crates/vite_global_cli/src/commands/version.rs b/crates/vite_global_cli/src/commands/version.rs index 6d420c1a0b..2723260eba 100644 --- a/crates/vite_global_cli/src/commands/version.rs +++ b/crates/vite_global_cli/src/commands/version.rs @@ -47,11 +47,7 @@ const TOOL_SPECS: [ToolSpec; 7] = [ package_name: "@voidzero-dev/vite-plus-core", bundled_version_key: Some("rolldown"), }, - ToolSpec { - display_name: "vitest", - package_name: "@voidzero-dev/vite-plus-test", - bundled_version_key: Some("vitest"), - }, + ToolSpec { display_name: "vitest", package_name: "vitest", bundled_version_key: None }, ToolSpec { display_name: "oxfmt", package_name: "oxfmt", bundled_version_key: None }, ToolSpec { display_name: "oxlint", package_name: "oxlint", bundled_version_key: None }, ToolSpec { diff --git a/crates/vite_migration/src/file_walker.rs b/crates/vite_migration/src/file_walker.rs index 9ab86a638c..83e4e48c7e 100644 --- a/crates/vite_migration/src/file_walker.rs +++ b/crates/vite_migration/src/file_walker.rs @@ -3,9 +3,12 @@ use std::path::{Path, PathBuf}; use ignore::WalkBuilder; use vite_error::Error; -// TODO: only support esm files for now -/// File extensions to process for import rewriting -const TS_JS_EXTENSIONS: &[&str] = &["ts", "tsx", "mts", "js", "jsx", "mjs"]; +/// File extensions to process for import rewriting. +/// +/// Includes CommonJS (`.cjs`/`.cts`) variants in addition to ESM, because +/// the legacy reverse-migration rules also cover `require('vite-plus/test/browser-*')` +/// calls that are most commonly found in `.cjs` / `vitest.config.cjs` files. +const TS_JS_EXTENSIONS: &[&str] = &["ts", "tsx", "mts", "cts", "js", "jsx", "mjs", "cjs"]; /// Result of walking TypeScript/JavaScript files #[derive(Debug)] @@ -164,7 +167,7 @@ mod tests { let result = find_ts_files(temp.path()).unwrap(); - assert_eq!(result.files.len(), 6); + assert_eq!(result.files.len(), 8); } #[test] diff --git a/docs/guide/migrate.md b/docs/guide/migrate.md index d84b010cce..36ca03ebcc 100644 --- a/docs/guide/migrate.md +++ b/docs/guide/migrate.md @@ -75,8 +75,8 @@ Migrate this project to Vite+. Vite+ replaces the current split tooling around r After the migration: - Confirm `vite` imports were rewritten to `vite-plus` where needed -- Confirm `vitest` imports were rewritten to `vite-plus/test` where needed -- Remove old `vite` and `vitest` dependencies only after those rewrites are confirmed +- Confirm `vitest/config` imports were rewritten to `vite-plus` (other `vitest` and `@vitest/browser*` imports are intentionally left as-is) +- Remove the old `vite` dependency only after those rewrites are confirmed; keep `vitest` and any `@vitest/browser*` providers - Move remaining tool-specific config into the appropriate blocks in `vite.config.ts` Command mapping to keep in mind: @@ -96,20 +96,28 @@ Summarize the migration at the end and report any manual follow-up still require ### Vitest -Vitest is automatically migrated through `vp migrate`. If you are migrating manually, you have to update all the imports to `vite-plus/test` instead: +`vp migrate` is the recommended path. It only rewrites `vitest/config` imports to `vite-plus`; all other Vitest imports are left untouched and resolve through the upstream `vitest` package as usual (`vite` is aliased to `@voidzero-dev/vite-plus-core` via overrides, so Vitest picks up the Vite+ core transparently). + +If you are migrating manually, update only the config entry point: ```ts // before -import { describe, expect, it, vi } from 'vitest'; - -const { page } = await import('@vitest/browser/context'); +import { defineConfig } from 'vitest/config'; // after -import { describe, expect, it, vi } from 'vite-plus/test'; +import { defineConfig } from 'vite-plus'; +``` -const { page } = await import('vite-plus/test/browser/context'); +Runtime imports stay as-is: + +```ts +import { describe, expect, it, vi } from 'vitest'; + +const { page } = await import('@vitest/browser/context'); ``` +Do not rewrite bare `vitest`, `vitest/*` subpaths, or `@vitest/browser*` — Vitest's mock hoister requires the literal string `'vitest'`, and the browser/provider subpaths are not re-exported by `vite-plus`. + ### tsdown If your project uses a `tsdown.config.ts`, move its options into the `pack` block in `vite.config.ts`: diff --git a/docs/guide/upgrade.md b/docs/guide/upgrade.md index 9b5c48e328..e0d5131b5f 100644 --- a/docs/guide/upgrade.md +++ b/docs/guide/upgrade.md @@ -29,21 +29,20 @@ You can also use `vp add vite-plus@latest` if you want to move the dependency ex ### Updating Aliased Packages -Vite+ sets up npm aliases for its core packages during installation: +Vite+ sets up an npm alias for its core package during installation: - `vite` is aliased to `npm:@voidzero-dev/vite-plus-core@latest` -- `vitest` is aliased to `npm:@voidzero-dev/vite-plus-test@latest` -`vp update vite-plus` does not re-resolve these aliases in the lockfile. To fully upgrade, update them separately: +`vp update vite-plus` does not re-resolve this alias in the lockfile. To fully upgrade, update it separately: ```bash -vp update @voidzero-dev/vite-plus-core @voidzero-dev/vite-plus-test +vp update @voidzero-dev/vite-plus-core ``` Or update everything at once: ```bash -vp update vite-plus @voidzero-dev/vite-plus-core @voidzero-dev/vite-plus-test +vp update vite-plus @voidzero-dev/vite-plus-core ``` You can verify with `vp outdated` that no Vite+ packages remain outdated. diff --git a/ecosystem-ci/patch-project.ts b/ecosystem-ci/patch-project.ts index 636fc399f9..38cf1303e6 100644 --- a/ecosystem-ci/patch-project.ts +++ b/ecosystem-ci/patch-project.ts @@ -55,9 +55,7 @@ execSync(`${cli} migrate --no-agent --no-interactive`, { ...(forceFreshMigration ? { VP_FORCE_MIGRATE: '1' } : {}), VP_OVERRIDE_PACKAGES: JSON.stringify({ vite: `file:${tgzDir}/voidzero-dev-vite-plus-core-0.0.0.tgz`, - vitest: `file:${tgzDir}/voidzero-dev-vite-plus-test-0.0.0.tgz`, '@voidzero-dev/vite-plus-core': `file:${tgzDir}/voidzero-dev-vite-plus-core-0.0.0.tgz`, - '@voidzero-dev/vite-plus-test': `file:${tgzDir}/voidzero-dev-vite-plus-test-0.0.0.tgz`, }), VP_VERSION: `file:${tgzDir}/vite-plus-0.0.0.tgz`, }, diff --git a/justfile b/justfile index 5410c99096..5aa395c8c5 100644 --- a/justfile +++ b/justfile @@ -47,7 +47,6 @@ build: pnpm --filter rolldown build-node pnpm --filter vite build-types pnpm --filter=@voidzero-dev/vite-plus-core build - pnpm --filter=@voidzero-dev/vite-plus-test build pnpm --filter=@voidzero-dev/vite-plus-prompts build pnpm --filter=vite-plus build diff --git a/packages/cli/BUNDLING.md b/packages/cli/BUNDLING.md index fa9ef3d792..7067afb7c9 100644 --- a/packages/cli/BUNDLING.md +++ b/packages/cli/BUNDLING.md @@ -1,6 +1,6 @@ # CLI Package Build Architecture -This document explains how `vite-plus` is built and how it re-exports from both the core and test packages to serve as a drop-in replacement for `vite`. +This document explains how `vite-plus` is built and how it re-exports from `@voidzero-dev/vite-plus-core` (bundled vite/rolldown/tsdown) and from upstream `vitest` to serve as a drop-in replacement for `vite`. ## Overview @@ -9,9 +9,9 @@ The CLI package uses a **4-step build process**: 1. **tsdown Build** - Bundle all CLI entry points via tsdown 2. **NAPI Binding Build** - Compile Rust code to native Node.js bindings 3. **Core Package Export Sync** - Re-export `@voidzero-dev/vite-plus-core` under `./client`, `./types/*`, etc. -4. **Test Package Export Sync** - Re-export `@voidzero-dev/vite-plus-test` under `./test/*` +4. **Test Package Export Sync** - Re-export upstream `vitest` under `./test/*` -This architecture allows users to import everything from a single package (`vite-plus`) as a drop-in replacement for `vite`, without needing to know about the separate core and test packages. +This architecture allows users to import everything from a single package (`vite-plus`) as a drop-in replacement for `vite`, without needing to know about the separate `@voidzero-dev/vite-plus-core` bundle or `vitest`. ## Build Steps @@ -24,7 +24,7 @@ Bundles all CLI entry points using tsdown (configured in `tsdown.config.ts`). Th - Public API entries: `bin`, `index`, `define-config`, `fmt`, `lint`, `pack`, `pack-bin` - Global command entries: `create`, `migrate`, `version`, `config`, `mcp`, `staged` - All third-party dependencies are inlined at build time -- Only packages that must be resolved at runtime stay external (NAPI binding, `@voidzero-dev/vite-plus-core`, `@voidzero-dev/vite-plus-test`, `oxfmt`, `oxlint`) +- Only packages that must be resolved at runtime stay external (NAPI binding, `@voidzero-dev/vite-plus-core`, `vitest`, `oxfmt`, `oxlint`) - Code splitting creates shared chunks for code used by multiple entries - DTS (`.d.ts`) files are generated for all entries @@ -90,15 +90,15 @@ export type * from '@voidzero-dev/vite-plus-core/types/importMeta.d.ts'; ### Step 4: Test Package Export Sync (`syncTestPackageExports`) -Reads the test package's exports and creates shim files that re-export everything under `./test/*`: +Reads vitest's exports and creates shim files that re-export everything under `./test/*`: ```typescript -// For each test package export like "./browser-playwright" +// For each vitest export like "./browser-playwright" // Creates a shim file: dist/test/browser-playwright.js -export * from '@voidzero-dev/vite-plus-test/browser-playwright'; +export * from 'vitest/browser-playwright'; ``` -**Input**: `../test/package.json` exports +**Input**: resolved `vitest/package.json` exports (resolved via `createRequire`) **Output**: `dist/test/*.js`, `dist/test/*.d.ts`, updated `package.json` exports --- @@ -336,28 +336,31 @@ This allows TypeScript to pick up types like `import.meta.hot`, CSS module types ### Why Shim Files? -Instead of copying the actual dist files from the test package, we create thin shim files that re-export from `@voidzero-dev/vite-plus-test`. This approach: +Instead of copying vitest's dist files, we create thin shim files that re-export from `vitest`. This approach: -1. **Keeps packages in sync** - No need to rebuild CLI when test package changes +1. **Keeps packages in sync** - No need to rebuild CLI when vitest is upgraded 2. **Reduces duplication** - No file copying, just re-exports -3. **Preserves module resolution** - Node.js resolves to the actual test package +3. **Preserves module resolution** - Node.js resolves to the actual installed vitest ### Export Mapping (Test) -All test package exports are mapped under `./test/*`: +Every entry under vitest's own `exports` is shimmed under `./test/*` (wildcard exports and `./package.json` are skipped). The shim is purely a re-export — `vite-plus/test` and friends are aliases for the matching subpath of upstream `vitest`. Examples: -| Test Package Export | CLI Package Export | -| ------------------------------------------------- | ----------------------------------- | -| `@voidzero-dev/vite-plus-test` | `vite-plus/test` | -| `@voidzero-dev/vite-plus-test/browser` | `vite-plus/test/browser` | -| `@voidzero-dev/vite-plus-test/browser-playwright` | `vite-plus/test/browser-playwright` | -| `@voidzero-dev/vite-plus-test/plugins/runner` | `vite-plus/test/plugins/runner` | +| Vitest Export | CLI Package Export | +| ------------------ | -------------------------- | +| `vitest` | `vite-plus/test` | +| `vitest/browser` | `vite-plus/test/browser` | +| `vitest/node` | `vite-plus/test/node` | +| `vitest/config` | `vite-plus/test/config` | +| `vitest/reporters` | `vite-plus/test/reporters` | + +The full set is regenerated on every build from the upstream vitest `package.json`, so the exact list tracks vitest itself. Browser provider packages (`@vitest/browser-playwright`, `@vitest/browser-preview`, `@vitest/browser-webdriverio`) and `@vitest/browser/context` are **not** re-exported — consume those directly from their original specifiers. ### Conditional Export Handling The sync handles complex conditional exports with `import`/`require`/`node`/`types` conditions. -**Test package's main export** (`"."`): +**Vitest's main export** (`"."`): ```json ".": { @@ -390,23 +393,23 @@ For each condition, appropriate shim files are created: ### Shim File Contents -**ESM shim** (`dist/test/browser-playwright.js`): +**ESM shim** (`dist/test/browser.js`): ```javascript -export * from '@voidzero-dev/vite-plus-test/browser-playwright'; +export * from 'vitest/browser'; ``` **CJS shim** (`dist/test/index.cjs`): ```javascript -module.exports = require('@voidzero-dev/vite-plus-test'); +module.exports = require('vitest'); ``` -**Type shim** (`dist/test/browser-playwright.d.ts`): +**Type shim** (`dist/test/browser.d.ts`): ```typescript -import '@voidzero-dev/vite-plus-test/browser-playwright'; -export * from '@voidzero-dev/vite-plus-test/browser-playwright'; +import 'vitest/browser'; +export * from 'vitest/browser'; ``` Note: Type shims include a side-effect import to preserve module augmentations (e.g., `toMatchSnapshot` on the `Assertion` interface). @@ -499,8 +502,8 @@ See `package.json` for the complete list of exports. // Core package name for Vite compatibility exports const CORE_PACKAGE_NAME = '@voidzero-dev/vite-plus-core'; -// Test package name for re-exports -const TEST_PACKAGE_NAME = '@voidzero-dev/vite-plus-test'; +// Test package name for re-exports (vitest itself, not a bundled wrapper) +const TEST_PACKAGE_NAME = 'vitest'; ``` ### Package.json Exports Management @@ -539,7 +542,7 @@ All non-`./test*` exports are manually maintained in `package.json`. These fall All `./test*` exports are fully managed by `syncTestPackageExports()`. The build script: -1. Reads `packages/test/package.json` exports +1. Reads vitest's `package.json` exports (resolved via `createRequire`) 2. Creates shim files in `dist/test/` 3. Removes old `./test*` exports from `package.json` 4. Merges in newly generated test exports diff --git a/packages/cli/README.md b/packages/cli/README.md index 8c3fcd71b0..4bcd953cb7 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -187,12 +187,11 @@ If you are manually migrating a project to Vite+, install these dev dependencies npm install -D vite-plus @voidzero-dev/vite-plus-core@latest ``` -You need to add overrides to your package manager for `vite` and `vitest` so that other packages depending on Vite and Vitest will use the Vite+ versions: +You need to add overrides to your package manager for `vite` so that other packages depending on Vite (including Vitest) will use the Vite+ version: ```json "overrides": { - "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest" + "vite": "npm:@voidzero-dev/vite-plus-core@latest" } ``` @@ -201,15 +200,13 @@ If you are using `pnpm`, add this to your `pnpm-workspace.yaml`: ```yaml overrides: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest ``` Or, if you are using Yarn: ```json "resolutions": { - "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest" + "vite": "npm:@voidzero-dev/vite-plus-core@latest" } ``` diff --git a/packages/cli/build.ts b/packages/cli/build.ts index c8ca718e61..5041728ca2 100644 --- a/packages/cli/build.ts +++ b/packages/cli/build.ts @@ -5,7 +5,7 @@ * 1. buildWithTsdown() - Bundles all CLI entry points via tsdown * 2. buildNapiBinding() - Builds the native Rust binding via NAPI * 3. syncCorePackageExports() - Creates shim files to re-export from @voidzero-dev/vite-plus-core - * 4. syncTestPackageExports() - Creates shim files to re-export from @voidzero-dev/vite-plus-test + * 4. syncTestPackageExports() - Creates shim files to re-export from vitest * 5. syncVersionsExport() - Generates ./versions module with bundled tool versions * 6. copyBundledDocs() - Copies docs into docs/ for bundled package access * 7. syncReadmeFromRoot() - Keeps package README in sync @@ -21,6 +21,7 @@ import { execSync } from 'node:child_process'; import { existsSync, readdirSync, statSync } from 'node:fs'; import { copyFile, cp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'; +import { createRequire } from 'node:module'; import { dirname, join, relative } from 'node:path'; import { fileURLToPath } from 'node:url'; import { parseArgs } from 'node:util'; @@ -30,12 +31,21 @@ import { format } from 'oxfmt'; import { generateLicenseFile } from '../../scripts/generate-license.js'; import corePkg from '../core/package.json' with { type: 'json' }; -import testPkg from '../test/package.json' with { type: 'json' }; const projectDir = dirname(fileURLToPath(import.meta.url)); -const TEST_PACKAGE_NAME = '@voidzero-dev/vite-plus-test'; +const TEST_PACKAGE_NAME = 'vitest'; const CORE_PACKAGE_NAME = '@voidzero-dev/vite-plus-core'; +// Browser providers projected under ./test/* and ./test/browser/providers/* so the +// public surface matches what the deleted `@voidzero-dev/vite-plus-test` wrapper exposed. +// Each entry maps the upstream package name to the short provider name used in the +// `./test/browser/providers/` alias path. +const BROWSER_PROVIDER_PACKAGES: ReadonlyArray<{ pkg: string; short: string }> = [ + { pkg: '@vitest/browser-playwright', short: 'playwright' }, + { pkg: '@vitest/browser-preview', short: 'preview' }, + { pkg: '@vitest/browser-webdriverio', short: 'webdriverio' }, +]; + const { values: { ['skip-native']: skipNative, ['skip-ts']: skipTs }, } = parseArgs({ @@ -278,16 +288,21 @@ async function syncTypesDir(srcDir: string, destDir: string, relativePath: strin } /** - * Sync exports from @voidzero-dev/vite-plus-test to vite-plus + * Sync exports from vitest to vite-plus * - * This function reads the test package's exports and creates shim files that + * This function reads vitest's package.json exports and creates shim files that * re-export everything under the ./test/* subpath. This allows users to import - * from vite-plus/test/* instead of @voidzero-dev/vite-plus-test/*. + * from vite-plus/test/* instead of vitest/*. */ async function syncTestPackageExports() { console.log('\nSyncing test package exports...'); - const testPkgPath = join(projectDir, '../test/package.json'); + // Resolve vitest's package.json via Node's resolver so we always read the + // currently installed copy — packages/test/ no longer exists. + const require = createRequire(import.meta.url); + const testPkgPath = require.resolve(`${TEST_PACKAGE_NAME}/package.json`, { + paths: [projectDir], + }); const cliPkgPath = join(projectDir, 'package.json'); const testDistDir = join(projectDir, 'dist/test'); @@ -309,15 +324,74 @@ async function syncTestPackageExports() { // Convert ./foo to ./test/foo, . to ./test const cliExportPath = exportPath === '.' ? './test' : `./test${exportPath.slice(1)}`; + const shimBaseName = exportPath === '.' ? 'index' : exportPath.slice(2); + const importSpecifier = + exportPath === '.' ? TEST_PACKAGE_NAME : `${TEST_PACKAGE_NAME}${exportPath.slice(1)}`; // Create shim files and build export entry - const shimExport = await createShimForExport(exportPath, exportValue, testDistDir); + const shimExport = await createShimForExport( + shimBaseName, + exportValue, + importSpecifier, + testDistDir, + ); if (shimExport) { generatedExports[cliExportPath] = shimExport; console.log(` Created ${cliExportPath}`); } } + // Mirror upstream @vitest/browser-* provider packages under ./test/ and + // ./test/browser/providers/. Existing vite-plus user code imports from these + // paths (e.g., `vite-plus/test/browser-playwright`) and must keep resolving after + // the bundled `@voidzero-dev/vite-plus-test` wrapper was removed. + for (const { pkg, short } of BROWSER_PROVIDER_PACKAGES) { + let providerPkgPath: string; + try { + providerPkgPath = require.resolve(`${pkg}/package.json`, { paths: [projectDir] }); + } catch (err) { + console.warn(` Skipping ${pkg} — not installed: ${(err as Error).message}`); + continue; + } + const providerPkg = JSON.parse(await readFile(providerPkgPath, 'utf-8')); + const providerExports = (providerPkg.exports ?? {}) as Record; + + for (const [providerExportPath, providerExportValue] of Object.entries(providerExports)) { + if (providerExportPath === './package.json' || providerExportPath.includes('*')) { + continue; + } + + const providerSubPath = providerExportPath === '.' ? '' : providerExportPath.slice(1); + // Two CLI surfaces that map to the same provider shim: + // ./test/ → e.g. ./test/browser-playwright + // ./test/browser/providers/ → e.g. ./test/browser/providers/playwright + const pkgShortName = pkg.startsWith('@vitest/') ? pkg.slice('@vitest/'.length) : pkg; + const surfaces = [ + { cliPath: `./test/${pkgShortName}${providerSubPath}`, baseName: `${pkgShortName}${providerSubPath}` }, + { + cliPath: `./test/browser/providers/${short}${providerSubPath}`, + baseName: `browser/providers/${short}${providerSubPath}`, + }, + ]; + const importSpecifier = + providerExportPath === '.' ? pkg : `${pkg}${providerExportPath.slice(1)}`; + + for (const { cliPath, baseName } of surfaces) { + const shimBaseName = baseName.replace(/^\//, ''); + const shimExport = await createShimForExport( + shimBaseName, + providerExportValue, + importSpecifier, + testDistDir, + ); + if (shimExport) { + generatedExports[cliPath] = shimExport; + console.log(` Created ${cliPath}`); + } + } + } + } + // Update CLI package.json await updateCliPackageJson(cliPkgPath, generatedExports); @@ -350,8 +424,8 @@ async function readDepVersion(packageName: string): Promise { * Generate ./versions export module with bundled tool versions. * * Collects versions from: - * - core/test package.json bundledVersions (vite, rolldown, tsdown, vitest) - * - CLI dependency package.json (oxlint, oxfmt, oxlint-tsgolint) + * - core package.json bundledVersions (vite, rolldown, tsdown) + * - CLI dependency package.json (oxlint, oxfmt, oxlint-tsgolint, vitest) * * Generates dist/versions.js and dist/versions.d.ts with inlined constants. */ @@ -359,15 +433,14 @@ async function syncVersionsExport() { console.log('\nSyncing versions export...'); const distDir = join(projectDir, 'dist'); - // Collect versions from bundledVersions (core + test) + // Collect bundled versions from the core package const versions: Record = { ...(corePkg as Record).bundledVersions, - ...(testPkg as Record).bundledVersions, }; - // Collect versions from CLI dependencies (oxlint, oxfmt, oxlint-tsgolint) - // These don't export ./package.json, so we read from node_modules directly - const depTools = ['oxlint', 'oxfmt', 'oxlint-tsgolint'] as const; + // Read versions from CLI dependencies' installed package.json files + // (these packages don't export ./package.json, so node_modules is the source of truth) + const depTools = ['oxlint', 'oxfmt', 'oxlint-tsgolint', 'vitest'] as const; for (const name of depTools) { const version = await readDepVersion(name); if (version) { @@ -468,19 +541,20 @@ type ExportValue = }; /** - * Create shim file(s) for a single export and return the export entry for package.json + * Create shim file(s) for a single export and return the export entry for package.json. + * + * @param shimBaseName Path under dist/test/ (e.g. 'index', 'config', 'browser-playwright/context'). + * @param exportValue The upstream package's export value for this entry. + * @param testImportSpecifier The bare import specifier the shim should re-export from + * (e.g. 'vitest', 'vitest/node', '@vitest/browser-playwright'). + * @param distDir Output dist/test directory. */ async function createShimForExport( - exportPath: string, + shimBaseName: string, exportValue: unknown, + testImportSpecifier: string, distDir: string, ): Promise { - // Determine the import specifier for the test package - const testImportSpecifier = - exportPath === '.' ? TEST_PACKAGE_NAME : `${TEST_PACKAGE_NAME}${exportPath.slice(1)}`; - - // Convert export path to file path: ./foo/bar -> foo/bar, . -> index - const shimBaseName = exportPath === '.' ? 'index' : exportPath.slice(2); const shimDir = join(distDir, dirname(shimBaseName)); await mkdir(shimDir, { recursive: true }); @@ -552,6 +626,11 @@ async function createShimForExport( * { import: { types, node, default }, require: { types, default } } * And flat structures like: * { types, require, default } + * + * Insertion order matters: Node.js package-exports conditions are order-sensitive. + * For dual-condition entries, `require` MUST come before `default` so that + * `require('vite-plus/test/config')` resolves to the `.cjs` shim instead of + * matching the catch-all `default` (which would point at the ESM file). */ async function createConditionalShim( value: Record, @@ -560,7 +639,11 @@ async function createConditionalShim( baseFileName: string, shimBaseName: string, ): Promise { - const result: ExportValue = {}; + // Build entries as an array of tuples so we control insertion order explicitly. + // Final order for flat entries: types, import (if present), require, default. + // `require` MUST come before `default` — `default` matches everything, so + // putting it first makes the `require` branch unreachable for CJS consumers. + const entries: Array<[string, ExportValue]> = []; // Handle top-level types (flat structure like { types, require, default }) if (value.types && typeof value.types === 'string' && !value.import) { @@ -570,14 +653,7 @@ async function createConditionalShim( dtsPath, `import '${testImportSpecifier}';\nexport * from '${testImportSpecifier}';\n`, ); - (result as Record).types = `./dist/test/${shimBaseName}.d.ts`; - } - - // Handle top-level default (flat structure, only when no import condition) - if (value.default && typeof value.default === 'string' && !value.import) { - const jsPath = join(shimDir, `${baseFileName}.js`); - await writeFile(jsPath, `export * from '${testImportSpecifier}';\n`); - (result as Record).default = `./dist/test/${shimBaseName}.js`; + entries.push(['types', `./dist/test/${shimBaseName}.d.ts`]); } // Handle import condition @@ -587,7 +663,7 @@ async function createConditionalShim( if (typeof importValue === 'string') { const jsPath = join(shimDir, `${baseFileName}.js`); await writeFile(jsPath, `export * from '${testImportSpecifier}';\n`); - (result as Record).import = `./dist/test/${shimBaseName}.js`; + entries.push(['import', `./dist/test/${shimBaseName}.js`]); } else if (typeof importValue === 'object' && importValue !== null) { const importResult: Record = {}; @@ -612,18 +688,19 @@ async function createConditionalShim( importResult.default = `./dist/test/${shimBaseName}.js`; } - result.import = importResult; + entries.push(['import', importResult]); } } - // Handle require condition + // Handle require condition — emitted BEFORE `default` so CJS resolution + // picks the `.cjs` shim instead of the catch-all `default` entry. if (value.require) { const requireValue = value.require as Record; if (typeof requireValue === 'string') { const cjsPath = join(shimDir, `${baseFileName}.cjs`); await writeFile(cjsPath, `module.exports = require('${testImportSpecifier}');\n`); - result.require = `./dist/test/${shimBaseName}.cjs`; + entries.push(['require', `./dist/test/${shimBaseName}.cjs`]); } else if (typeof requireValue === 'object' && requireValue !== null) { const requireResult: Record = {}; @@ -643,11 +720,20 @@ async function createConditionalShim( requireResult.default = `./dist/test/${shimBaseName}.cjs`; } - result.require = requireResult; + entries.push(['require', requireResult]); } } - return result; + // Handle top-level default (flat structure, only when no import condition). + // Emitted LAST among siblings so `require` (and any specific condition) + // wins resolution against the catch-all `default`. + if (value.default && typeof value.default === 'string' && !value.import) { + const jsPath = join(shimDir, `${baseFileName}.js`); + await writeFile(jsPath, `export * from '${testImportSpecifier}';\n`); + entries.push(['default', `./dist/test/${shimBaseName}.js`]); + } + + return Object.fromEntries(entries) as ExportValue; } /** diff --git a/packages/cli/package.json b/packages/cli/package.json index 6dfcf73ff3..08d2ce5ac3 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -96,7 +96,6 @@ "./test": { "import": { "types": "./dist/test/index.d.ts", - "node": "./dist/test/index.js", "default": "./dist/test/index.js" }, "require": { @@ -148,8 +147,8 @@ }, "./test/config": { "types": "./dist/test/config.d.ts", - "default": "./dist/test/config.js", - "require": "./dist/test/config.cjs" + "require": "./dist/test/config.cjs", + "default": "./dist/test/config.js" }, "./test/coverage": { "types": "./dist/test/coverage.d.ts", @@ -171,160 +170,47 @@ "types": "./dist/test/worker.d.ts", "default": "./dist/test/worker.js" }, - "./test/browser-compat": { - "default": "./dist/test/browser-compat.js" - }, - "./test/client": { - "default": "./dist/test/client.js" - }, - "./test/context": { - "types": "./dist/test/context.d.ts", - "default": "./dist/test/context.js" - }, - "./test/browser/context": { - "types": "./dist/test/browser/context.d.ts", - "default": "./dist/test/browser/context.js" - }, - "./test/locators": { - "default": "./dist/test/locators.js" - }, - "./test/matchers": { - "default": "./dist/test/matchers.js" - }, - "./test/utils": { - "default": "./dist/test/utils.js" - }, "./test/browser-playwright": { "types": "./dist/test/browser-playwright.d.ts", "default": "./dist/test/browser-playwright.js" }, - "./test/browser-webdriverio": { - "types": "./dist/test/browser-webdriverio.d.ts", - "default": "./dist/test/browser-webdriverio.js" - }, - "./test/browser-preview": { - "types": "./dist/test/browser-preview.d.ts", - "default": "./dist/test/browser-preview.js" - }, "./test/browser/providers/playwright": { "types": "./dist/test/browser/providers/playwright.d.ts", "default": "./dist/test/browser/providers/playwright.js" }, - "./test/browser/providers/webdriverio": { - "types": "./dist/test/browser/providers/webdriverio.d.ts", - "default": "./dist/test/browser/providers/webdriverio.js" + "./test/browser-playwright/context": { + "types": "./dist/test/browser-playwright/context.d.ts" + }, + "./test/browser/providers/playwright/context": { + "types": "./dist/test/browser/providers/playwright/context.d.ts" + }, + "./test/browser-preview": { + "types": "./dist/test/browser-preview.d.ts", + "default": "./dist/test/browser-preview.js" }, "./test/browser/providers/preview": { "types": "./dist/test/browser/providers/preview.d.ts", "default": "./dist/test/browser/providers/preview.js" }, - "./test/plugins/runner": { - "default": "./dist/test/plugins/runner.js" - }, - "./test/plugins/runner-utils": { - "default": "./dist/test/plugins/runner-utils.js" - }, - "./test/plugins/runner-types": { - "default": "./dist/test/plugins/runner-types.js" - }, - "./test/plugins/utils": { - "default": "./dist/test/plugins/utils.js" - }, - "./test/plugins/utils-source-map": { - "default": "./dist/test/plugins/utils-source-map.js" - }, - "./test/plugins/utils-source-map-node": { - "default": "./dist/test/plugins/utils-source-map-node.js" - }, - "./test/plugins/utils-error": { - "default": "./dist/test/plugins/utils-error.js" - }, - "./test/plugins/utils-helpers": { - "default": "./dist/test/plugins/utils-helpers.js" + "./test/browser-preview/context": { + "types": "./dist/test/browser-preview/context.d.ts" }, - "./test/plugins/utils-display": { - "default": "./dist/test/plugins/utils-display.js" + "./test/browser/providers/preview/context": { + "types": "./dist/test/browser/providers/preview/context.d.ts" }, - "./test/plugins/utils-timers": { - "default": "./dist/test/plugins/utils-timers.js" - }, - "./test/plugins/utils-highlight": { - "default": "./dist/test/plugins/utils-highlight.js" - }, - "./test/plugins/utils-offset": { - "default": "./dist/test/plugins/utils-offset.js" - }, - "./test/plugins/utils-resolver": { - "default": "./dist/test/plugins/utils-resolver.js" - }, - "./test/plugins/utils-serialize": { - "default": "./dist/test/plugins/utils-serialize.js" - }, - "./test/plugins/utils-constants": { - "default": "./dist/test/plugins/utils-constants.js" - }, - "./test/plugins/utils-diff": { - "default": "./dist/test/plugins/utils-diff.js" - }, - "./test/plugins/spy": { - "default": "./dist/test/plugins/spy.js" - }, - "./test/plugins/expect": { - "default": "./dist/test/plugins/expect.js" - }, - "./test/plugins/snapshot": { - "default": "./dist/test/plugins/snapshot.js" - }, - "./test/plugins/snapshot-environment": { - "default": "./dist/test/plugins/snapshot-environment.js" - }, - "./test/plugins/snapshot-manager": { - "default": "./dist/test/plugins/snapshot-manager.js" - }, - "./test/plugins/mocker": { - "default": "./dist/test/plugins/mocker.js" - }, - "./test/plugins/mocker-node": { - "default": "./dist/test/plugins/mocker-node.js" - }, - "./test/plugins/mocker-browser": { - "default": "./dist/test/plugins/mocker-browser.js" - }, - "./test/plugins/mocker-redirect": { - "default": "./dist/test/plugins/mocker-redirect.js" - }, - "./test/plugins/mocker-transforms": { - "default": "./dist/test/plugins/mocker-transforms.js" - }, - "./test/plugins/mocker-automock": { - "default": "./dist/test/plugins/mocker-automock.js" - }, - "./test/plugins/mocker-register": { - "default": "./dist/test/plugins/mocker-register.js" - }, - "./test/plugins/pretty-format": { - "default": "./dist/test/plugins/pretty-format.js" - }, - "./test/plugins/browser": { - "default": "./dist/test/plugins/browser.js" - }, - "./test/plugins/browser-context": { - "default": "./dist/test/plugins/browser-context.js" - }, - "./test/plugins/browser-client": { - "default": "./dist/test/plugins/browser-client.js" - }, - "./test/plugins/browser-locators": { - "default": "./dist/test/plugins/browser-locators.js" + "./test/browser-webdriverio": { + "types": "./dist/test/browser-webdriverio.d.ts", + "default": "./dist/test/browser-webdriverio.js" }, - "./test/plugins/browser-playwright": { - "default": "./dist/test/plugins/browser-playwright.js" + "./test/browser/providers/webdriverio": { + "types": "./dist/test/browser/providers/webdriverio.d.ts", + "default": "./dist/test/browser/providers/webdriverio.js" }, - "./test/plugins/browser-webdriverio": { - "default": "./dist/test/plugins/browser-webdriverio.js" + "./test/browser-webdriverio/context": { + "types": "./dist/test/browser-webdriverio/context.d.ts" }, - "./test/plugins/browser-preview": { - "default": "./dist/test/plugins/browser-preview.js" + "./test/browser/providers/webdriverio/context": { + "types": "./dist/test/browser/providers/webdriverio/context.d.ts" } }, "scripts": { @@ -340,11 +226,15 @@ "dependencies": { "@oxc-project/types": "catalog:", "@oxlint/plugins": "catalog:", + "@vitest/browser": "catalog:", + "@vitest/browser-playwright": "catalog:", + "@vitest/browser-preview": "catalog:", + "@vitest/browser-webdriverio": "catalog:", "@voidzero-dev/vite-plus-core": "workspace:*", - "@voidzero-dev/vite-plus-test": "workspace:*", "oxfmt": "catalog:", "oxlint": "catalog:", - "oxlint-tsgolint": "catalog:" + "oxlint-tsgolint": "catalog:", + "vitest": "catalog:" }, "devDependencies": { "@napi-rs/cli": "catalog:", diff --git a/packages/cli/publish-native-addons.ts b/packages/cli/publish-native-addons.ts index ed9c5c51f2..b9dfb3dd35 100644 --- a/packages/cli/publish-native-addons.ts +++ b/packages/cli/publish-native-addons.ts @@ -53,12 +53,6 @@ if (existsSync(rustCliArtifactsDir)) { } } -// Build test package — versions are already bumped on main by prepare_release.yml. -execSync('pnpm --filter=@voidzero-dev/vite-plus-test build', { - cwd: repoRoot, - stdio: 'inherit', -}); - // Create npm directories for NAPI bindings await cli.createNpmDirs({ cwd: currentDir, diff --git a/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt b/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt index c98f4e9d51..0d9643f560 100644 --- a/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt @@ -21,18 +21,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat .vite-hooks/pre-commit # check pre-commit hook vp staged diff --git a/packages/cli/snap-tests-global/migration-auto-create-vite-config/snap.txt b/packages/cli/snap-tests-global/migration-auto-create-vite-config/snap.txt index 00f949c269..79173673fa 100644 --- a/packages/cli/snap-tests-global/migration-auto-create-vite-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-auto-create-vite-config/snap.txt @@ -51,15 +51,11 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-baseurl-tsconfig/snap.txt b/packages/cli/snap-tests-global/migration-baseurl-tsconfig/snap.txt index 3b6e2574fa..37ffa0d8a2 100644 --- a/packages/cli/snap-tests-global/migration-baseurl-tsconfig/snap.txt +++ b/packages/cli/snap-tests-global/migration-baseurl-tsconfig/snap.txt @@ -44,15 +44,11 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-chained-lint-staged-pre-commit/snap.txt b/packages/cli/snap-tests-global/migration-chained-lint-staged-pre-commit/snap.txt index bf72628953..36d6c12f9e 100644 --- a/packages/cli/snap-tests-global/migration-chained-lint-staged-pre-commit/snap.txt +++ b/packages/cli/snap-tests-global/migration-chained-lint-staged-pre-commit/snap.txt @@ -21,18 +21,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt b/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt index 27fed7c01c..9e82198b08 100644 --- a/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt +++ b/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt @@ -21,18 +21,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat .config/husky/pre-commit # pre-commit hook should be in custom dir vp staged diff --git a/packages/cli/snap-tests-global/migration-composed-husky-prepare/snap.txt b/packages/cli/snap-tests-global/migration-composed-husky-prepare/snap.txt index 0b78cecfe4..a984ee4628 100644 --- a/packages/cli/snap-tests-global/migration-composed-husky-prepare/snap.txt +++ b/packages/cli/snap-tests-global/migration-composed-husky-prepare/snap.txt @@ -21,15 +21,11 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-env-prefix-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-env-prefix-lint-staged/snap.txt index 1aa424701f..fe31dc1fb8 100644 --- a/packages/cli/snap-tests-global/migration-env-prefix-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-env-prefix-lint-staged/snap.txt @@ -21,18 +21,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-eslint-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-eslint-lint-staged/snap.txt index cb4a72420f..49a3c5cf45 100644 --- a/packages/cli/snap-tests-global/migration-eslint-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-eslint-lint-staged/snap.txt @@ -21,18 +21,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat vite.config.ts # check oxlint config and staged config merged into vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-eslint-lintstagedrc/snap.txt b/packages/cli/snap-tests-global/migration-eslint-lintstagedrc/snap.txt index a62041e3a1..139ee5c82d 100644 --- a/packages/cli/snap-tests-global/migration-eslint-lintstagedrc/snap.txt +++ b/packages/cli/snap-tests-global/migration-eslint-lintstagedrc/snap.txt @@ -21,18 +21,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > test ! -f .lintstagedrc.json # check lintstagedrc.json is removed > cat vite.config.ts # check oxlint config merged into vite.config.ts diff --git a/packages/cli/snap-tests-global/migration-eslint-npx-wrapper/snap.txt b/packages/cli/snap-tests-global/migration-eslint-npx-wrapper/snap.txt index ce804c1e0b..92fde94658 100644 --- a/packages/cli/snap-tests-global/migration-eslint-npx-wrapper/snap.txt +++ b/packages/cli/snap-tests-global/migration-eslint-npx-wrapper/snap.txt @@ -26,17 +26,13 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > test ! -f eslint.config.mjs # check eslint config is removed \ No newline at end of file diff --git a/packages/cli/snap-tests-global/migration-eslint/snap.txt b/packages/cli/snap-tests-global/migration-eslint/snap.txt index 636589b8c2..5a00331f20 100644 --- a/packages/cli/snap-tests-global/migration-eslint/snap.txt +++ b/packages/cli/snap-tests-global/migration-eslint/snap.txt @@ -24,18 +24,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > test ! -f eslint.config.mjs # check eslint config is removed > cat vite.config.ts # check oxlint config merged into vite.config.ts diff --git a/packages/cli/snap-tests-global/migration-existing-husky-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-existing-husky-lint-staged/snap.txt index 067d68aba6..c29eb91e22 100644 --- a/packages/cli/snap-tests-global/migration-existing-husky-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-husky-lint-staged/snap.txt @@ -21,18 +21,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-existing-husky-v8-hooks/snap.txt b/packages/cli/snap-tests-global/migration-existing-husky-v8-hooks/snap.txt index 72ac97116d..c625deb5d5 100644 --- a/packages/cli/snap-tests-global/migration-existing-husky-v8-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-husky-v8-hooks/snap.txt @@ -24,18 +24,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat .husky/pre-commit # hook file should be unchanged (still has bootstrap) . "$(dirname -- "$0")/_/husky.sh" diff --git a/packages/cli/snap-tests-global/migration-existing-husky-v8-multi-hooks/snap.txt b/packages/cli/snap-tests-global/migration-existing-husky-v8-multi-hooks/snap.txt index e9c4d445c6..dff5aecefc 100644 --- a/packages/cli/snap-tests-global/migration-existing-husky-v8-multi-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-husky-v8-multi-hooks/snap.txt @@ -24,18 +24,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat .husky/pre-commit # hook file should be unchanged (still has bootstrap) . "$(dirname -- "$0")/_/husky.sh" diff --git a/packages/cli/snap-tests-global/migration-existing-husky/snap.txt b/packages/cli/snap-tests-global/migration-existing-husky/snap.txt index 260a9e510c..1bd95c9a83 100644 --- a/packages/cli/snap-tests-global/migration-existing-husky/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-husky/snap.txt @@ -21,18 +21,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat .vite-hooks/pre-commit # check pre-commit hook rewritten to vp staged vp staged diff --git a/packages/cli/snap-tests-global/migration-existing-lint-staged-config/snap.txt b/packages/cli/snap-tests-global/migration-existing-lint-staged-config/snap.txt index bc0f54cc72..7798f51a5c 100644 --- a/packages/cli/snap-tests-global/migration-existing-lint-staged-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-lint-staged-config/snap.txt @@ -21,18 +21,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > test ! -f .lintstagedrc.json # check lintstagedrc.json (should be deleted after inlining to vite.config.ts) > cat vite.config.ts # check staged config migrated to vite.config.ts diff --git a/packages/cli/snap-tests-global/migration-existing-pnpm-exec-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-existing-pnpm-exec-lint-staged/snap.txt index 96c9e19d94..0eb55dd9ed 100644 --- a/packages/cli/snap-tests-global/migration-existing-pnpm-exec-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-pnpm-exec-lint-staged/snap.txt @@ -21,18 +21,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-existing-prepare-script/snap.txt b/packages/cli/snap-tests-global/migration-existing-prepare-script/snap.txt index 3df5a5ee3e..1ebbe16262 100644 --- a/packages/cli/snap-tests-global/migration-existing-prepare-script/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-prepare-script/snap.txt @@ -22,18 +22,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat .vite-hooks/pre-commit # check pre-commit hook vp staged diff --git a/packages/cli/snap-tests-global/migration-from-tsdown-json-config/snap.txt b/packages/cli/snap-tests-global/migration-from-tsdown-json-config/snap.txt index cff5f38ba1..4690b8400a 100644 --- a/packages/cli/snap-tests-global/migration-from-tsdown-json-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-tsdown-json-config/snap.txt @@ -46,18 +46,14 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > vp migrate --no-interactive # run migration again to check if it is idempotent This project is already using Vite+! Happy coding! diff --git a/packages/cli/snap-tests-global/migration-from-tsdown/snap.txt b/packages/cli/snap-tests-global/migration-from-tsdown/snap.txt index 2da336e742..87f3ea24de 100644 --- a/packages/cli/snap-tests-global/migration-from-tsdown/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-tsdown/snap.txt @@ -48,18 +48,14 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > vp migrate --no-interactive # run migration again to check if it is idempotent This project is already using Vite+! Happy coding! diff --git a/packages/cli/snap-tests-global/migration-from-vitest-config/snap.txt b/packages/cli/snap-tests-global/migration-from-vitest-config/snap.txt index 0c3d5fe6f3..5f2b83d5d1 100644 --- a/packages/cli/snap-tests-global/migration-from-vitest-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-vitest-config/snap.txt @@ -41,7 +41,7 @@ export default defineConfig({ }, "devDependencies": { "vite": "catalog:", - "vitest": "catalog:", + "vitest": "^4.0.0", "playwright": "*", "vite-plus": "catalog:" }, @@ -51,15 +51,11 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt b/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt index 0b688b13bf..b934c5d0d3 100644 --- a/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt @@ -16,7 +16,7 @@ }, "devDependencies": { "vite": "catalog:", - "vitest": "catalog:", + "vitest": "^4.0.0", "playwright": "*", "vite-plus": "catalog:" }, @@ -26,18 +26,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat test/hello.ts # check test/hello.ts import { server } from 'vite-plus/test/browser-playwright/context'; diff --git a/packages/cli/snap-tests-global/migration-hooks-skip-on-existing-hookspath/snap.txt b/packages/cli/snap-tests-global/migration-hooks-skip-on-existing-hookspath/snap.txt index 2fde12c7ed..47331d89bc 100644 --- a/packages/cli/snap-tests-global/migration-hooks-skip-on-existing-hookspath/snap.txt +++ b/packages/cli/snap-tests-global/migration-hooks-skip-on-existing-hookspath/snap.txt @@ -24,18 +24,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > git config --local core.hooksPath # should still be .custom-hooks .custom-hooks diff --git a/packages/cli/snap-tests-global/migration-husky-latest-dist-tag-v9-installed/snap.txt b/packages/cli/snap-tests-global/migration-husky-latest-dist-tag-v9-installed/snap.txt index 4d39f8f03b..f58a4409d3 100644 --- a/packages/cli/snap-tests-global/migration-husky-latest-dist-tag-v9-installed/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-latest-dist-tag-v9-installed/snap.txt @@ -21,15 +21,11 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-husky-latest-dist-tag/snap.txt b/packages/cli/snap-tests-global/migration-husky-latest-dist-tag/snap.txt index 88721e1e3a..93f1f3a31c 100644 --- a/packages/cli/snap-tests-global/migration-husky-latest-dist-tag/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-latest-dist-tag/snap.txt @@ -23,15 +23,11 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-husky-or-prepare/snap.txt b/packages/cli/snap-tests-global/migration-husky-or-prepare/snap.txt index a98449620e..b24875fd8c 100644 --- a/packages/cli/snap-tests-global/migration-husky-or-prepare/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-or-prepare/snap.txt @@ -21,15 +21,11 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-husky-semicolon-prepare/snap.txt b/packages/cli/snap-tests-global/migration-husky-semicolon-prepare/snap.txt index 42df326a40..0e612095b7 100644 --- a/packages/cli/snap-tests-global/migration-husky-semicolon-prepare/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-semicolon-prepare/snap.txt @@ -21,15 +21,11 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-husky-v8-preserves-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-husky-v8-preserves-lint-staged/snap.txt index d56772a22d..96986e2b14 100644 --- a/packages/cli/snap-tests-global/migration-husky-v8-preserves-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-v8-preserves-lint-staged/snap.txt @@ -27,15 +27,11 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-lint-staged-in-scripts/snap.txt b/packages/cli/snap-tests-global/migration-lint-staged-in-scripts/snap.txt index 86da8a68b4..221633b129 100644 --- a/packages/cli/snap-tests-global/migration-lint-staged-in-scripts/snap.txt +++ b/packages/cli/snap-tests-global/migration-lint-staged-in-scripts/snap.txt @@ -22,18 +22,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-lint-staged-merge-fail/snap.txt b/packages/cli/snap-tests-global/migration-lint-staged-merge-fail/snap.txt index 910f89ebd1..b899c09edc 100644 --- a/packages/cli/snap-tests-global/migration-lint-staged-merge-fail/snap.txt +++ b/packages/cli/snap-tests-global/migration-lint-staged-merge-fail/snap.txt @@ -30,18 +30,14 @@ Please add staged config to vite.config.ts manually, see https://viteplus.dev/gu > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat vite.config.ts # vite config should be unchanged (merge failed) const config = { plugins: [] }; diff --git a/packages/cli/snap-tests-global/migration-lint-staged-ts-config/snap.txt b/packages/cli/snap-tests-global/migration-lint-staged-ts-config/snap.txt index 0644922652..8084759590 100644 --- a/packages/cli/snap-tests-global/migration-lint-staged-ts-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-lint-staged-ts-config/snap.txt @@ -25,18 +25,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat lint-staged.config.ts # check TS config is not modified export default { diff --git a/packages/cli/snap-tests-global/migration-lintstagedrc-json/snap.txt b/packages/cli/snap-tests-global/migration-lintstagedrc-json/snap.txt index e2ad6ee309..03e14d64d2 100644 --- a/packages/cli/snap-tests-global/migration-lintstagedrc-json/snap.txt +++ b/packages/cli/snap-tests-global/migration-lintstagedrc-json/snap.txt @@ -93,18 +93,14 @@ Documentation: https://viteplus.dev/guide/migrate > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-lintstagedrc-merge-fail/snap.txt b/packages/cli/snap-tests-global/migration-lintstagedrc-merge-fail/snap.txt index dc4b6e426a..becb210241 100644 --- a/packages/cli/snap-tests-global/migration-lintstagedrc-merge-fail/snap.txt +++ b/packages/cli/snap-tests-global/migration-lintstagedrc-merge-fail/snap.txt @@ -27,18 +27,14 @@ Please add staged config to vite.config.ts manually, see https://viteplus.dev/gu > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat .lintstagedrc.json # config file should be preserved when merge fails { diff --git a/packages/cli/snap-tests-global/migration-lintstagedrc-not-support/snap.txt b/packages/cli/snap-tests-global/migration-lintstagedrc-not-support/snap.txt index 8171e7d079..10eec58cc3 100644 --- a/packages/cli/snap-tests-global/migration-lintstagedrc-not-support/snap.txt +++ b/packages/cli/snap-tests-global/migration-lintstagedrc-not-support/snap.txt @@ -38,15 +38,11 @@ export default { > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-lintstagedrc-staged-exists/snap.txt b/packages/cli/snap-tests-global/migration-lintstagedrc-staged-exists/snap.txt index 0bc94af760..e5f88903c8 100644 --- a/packages/cli/snap-tests-global/migration-lintstagedrc-staged-exists/snap.txt +++ b/packages/cli/snap-tests-global/migration-lintstagedrc-staged-exists/snap.txt @@ -22,18 +22,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > test -f .lintstagedrc.json && echo 'lintstagedrc.json still exists' || echo 'lintstagedrc.json was deleted' # should still exist lintstagedrc.json still exists diff --git a/packages/cli/snap-tests-global/migration-merge-vite-config-js/snap.txt b/packages/cli/snap-tests-global/migration-merge-vite-config-js/snap.txt index 5a6900d06e..8c69853ed1 100644 --- a/packages/cli/snap-tests-global/migration-merge-vite-config-js/snap.txt +++ b/packages/cli/snap-tests-global/migration-merge-vite-config-js/snap.txt @@ -50,15 +50,11 @@ export default { > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-merge-vite-config-ts/snap.txt b/packages/cli/snap-tests-global/migration-merge-vite-config-ts/snap.txt index e24fa6682a..54c3ab4c81 100644 --- a/packages/cli/snap-tests-global/migration-merge-vite-config-ts/snap.txt +++ b/packages/cli/snap-tests-global/migration-merge-vite-config-ts/snap.txt @@ -74,7 +74,7 @@ export default defineConfig({ "devDependencies": { "@vitejs/plugin-react": "^4.2.0", "vite": "catalog:", - "vitest": "catalog:", + "vitest": "^4.0.0", "playwright": "*", "vite-plus": "catalog:" }, @@ -84,15 +84,11 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-monorepo-bun/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-bun/snap.txt index 144d97ebb0..d6d8373235 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-bun/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-bun/snap.txt @@ -44,7 +44,7 @@ export default defineConfig({ ], "catalog": { "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest", + "vitest": "^4.1.5", "vite-plus": "latest" } }, @@ -67,8 +67,7 @@ export default defineConfig({ }, "packageManager": "bun@", "overrides": { - "vite": "catalog:", - "vitest": "catalog:" + "vite": "catalog:" } } diff --git a/packages/cli/snap-tests-global/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt index 5b8caecfe3..26c1b943f7 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt @@ -38,22 +38,18 @@ packages: catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: '@vitejs/plugin-react>vite': 'npm:vite@' 'supertest>superagent': vite: 'catalog:' - vitest: 'catalog:' react-click-away-listener>react: peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat packages/app/package.json # check app package.json { diff --git a/packages/cli/snap-tests-global/migration-monorepo-pnpm/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-pnpm/snap.txt index f877dfd403..7311e6729f 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-pnpm/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-pnpm/snap.txt @@ -69,6 +69,7 @@ export default defineConfig({ "vite-plus": "catalog:" }, "resolutions": { + "vitest": "catalog:", "vue": "3.5.25" }, "packageManager": "pnpm@" @@ -82,20 +83,17 @@ catalog: testnpm2: ^1.0.0 # test comment here to check if the comment is preserved vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest + vitest: ^4.0.0 vite-plus: latest minimumReleaseAge: 1440 overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' minimumReleaseAgeExclude: - vite-plus - '@voidzero-dev/*' diff --git a/packages/cli/snap-tests-global/migration-monorepo-yarn4/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-yarn4/snap.txt index 0874f30c30..87fca132a8 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-yarn4/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-yarn4/snap.txt @@ -64,8 +64,7 @@ export default defineConfig({ }, "packageManager": "yarn@", "resolutions": { - "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest" + "vite": "npm:@voidzero-dev/vite-plus-core@latest" } } @@ -73,7 +72,6 @@ export default defineConfig({ nodeLinker: node-modules catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest > cat packages/app/package.json # check app package.json diff --git a/packages/cli/snap-tests-global/migration-no-git-repo/snap.txt b/packages/cli/snap-tests-global/migration-no-git-repo/snap.txt index c31403fd00..4cd2b51d70 100644 --- a/packages/cli/snap-tests-global/migration-no-git-repo/snap.txt +++ b/packages/cli/snap-tests-global/migration-no-git-repo/snap.txt @@ -19,18 +19,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > test -d .vite-hooks && echo 'hooks dir exists' || echo 'no hooks dir' hooks dir exists diff --git a/packages/cli/snap-tests-global/migration-no-hooks-with-husky/snap.txt b/packages/cli/snap-tests-global/migration-no-hooks-with-husky/snap.txt index 74aa2b4f85..5339190285 100644 --- a/packages/cli/snap-tests-global/migration-no-hooks-with-husky/snap.txt +++ b/packages/cli/snap-tests-global/migration-no-hooks-with-husky/snap.txt @@ -26,18 +26,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > test -d .husky && echo '.husky directory exists' || echo 'No .husky directory' # verify no .husky directory No .husky directory diff --git a/packages/cli/snap-tests-global/migration-no-hooks/snap.txt b/packages/cli/snap-tests-global/migration-no-hooks/snap.txt index 925cb2962f..90d7d48ba2 100644 --- a/packages/cli/snap-tests-global/migration-no-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-no-hooks/snap.txt @@ -17,18 +17,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > test -d .vite-hooks && echo '.vite-hooks directory exists' || echo 'No .vite-hooks directory' # verify no .vite-hooks directory No .vite-hooks directory diff --git a/packages/cli/snap-tests-global/migration-other-hook-tool/snap.txt b/packages/cli/snap-tests-global/migration-other-hook-tool/snap.txt index eef56238fe..7c8162ae5b 100644 --- a/packages/cli/snap-tests-global/migration-other-hook-tool/snap.txt +++ b/packages/cli/snap-tests-global/migration-other-hook-tool/snap.txt @@ -29,15 +29,11 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-oxlintrc-json-with-comments/snap.txt b/packages/cli/snap-tests-global/migration-oxlintrc-json-with-comments/snap.txt index b140b1981d..1c6816b637 100644 --- a/packages/cli/snap-tests-global/migration-oxlintrc-json-with-comments/snap.txt +++ b/packages/cli/snap-tests-global/migration-oxlintrc-json-with-comments/snap.txt @@ -49,15 +49,11 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-oxlintrc-jsonc/snap.txt b/packages/cli/snap-tests-global/migration-oxlintrc-jsonc/snap.txt index 88d3d51bac..355b2ecb59 100644 --- a/packages/cli/snap-tests-global/migration-oxlintrc-jsonc/snap.txt +++ b/packages/cli/snap-tests-global/migration-oxlintrc-jsonc/snap.txt @@ -51,15 +51,11 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-partially-migrated-pre-commit/snap.txt b/packages/cli/snap-tests-global/migration-partially-migrated-pre-commit/snap.txt index ec77acdd83..6c63f873c8 100644 --- a/packages/cli/snap-tests-global/migration-partially-migrated-pre-commit/snap.txt +++ b/packages/cli/snap-tests-global/migration-partially-migrated-pre-commit/snap.txt @@ -24,18 +24,14 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat .husky/pre-commit # hook file should be unchanged (still has bootstrap) . "$(dirname -- "$0")/_/husky.sh" diff --git a/packages/cli/snap-tests-global/migration-prettier-eslint-combo/snap.txt b/packages/cli/snap-tests-global/migration-prettier-eslint-combo/snap.txt index 58db2eeebd..a7e02fda63 100644 --- a/packages/cli/snap-tests-global/migration-prettier-eslint-combo/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier-eslint-combo/snap.txt @@ -28,18 +28,14 @@ Prettier configuration detected. Auto-migrating to Oxfmt... > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > test ! -f eslint.config.mjs # check eslint config is removed > test ! -f .prettierrc.json # check prettier config is removed diff --git a/packages/cli/snap-tests-global/migration-prettier-ignore-unknown/snap.txt b/packages/cli/snap-tests-global/migration-prettier-ignore-unknown/snap.txt index 9bae37b1c3..f22e548c62 100644 --- a/packages/cli/snap-tests-global/migration-prettier-ignore-unknown/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier-ignore-unknown/snap.txt @@ -26,17 +26,13 @@ Prettier configuration detected. Auto-migrating to Oxfmt... > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > test ! -f .prettierrc.json # check prettier config is removed \ No newline at end of file diff --git a/packages/cli/snap-tests-global/migration-prettier-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-prettier-lint-staged/snap.txt index 4f54aaf230..c810f4790f 100644 --- a/packages/cli/snap-tests-global/migration-prettier-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier-lint-staged/snap.txt @@ -23,18 +23,14 @@ Prettier configuration detected. Auto-migrating to Oxfmt... > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat vite.config.ts # check oxfmt config and staged config merged into vite.config.ts import { defineConfig } from "vite-plus"; diff --git a/packages/cli/snap-tests-global/migration-prettier-pkg-json/snap.txt b/packages/cli/snap-tests-global/migration-prettier-pkg-json/snap.txt index f788ee36e4..23ccc2c07f 100644 --- a/packages/cli/snap-tests-global/migration-prettier-pkg-json/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier-pkg-json/snap.txt @@ -24,18 +24,14 @@ Prettier configuration detected. Auto-migrating to Oxfmt... > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > cat vite.config.ts # check oxfmt config merged into vite.config.ts with semi/singleQuote settings import { defineConfig } from "vite-plus"; diff --git a/packages/cli/snap-tests-global/migration-prettier/snap.txt b/packages/cli/snap-tests-global/migration-prettier/snap.txt index a9064ccaed..7614ea5882 100644 --- a/packages/cli/snap-tests-global/migration-prettier/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier/snap.txt @@ -26,18 +26,14 @@ Prettier configuration detected. Auto-migrating to Oxfmt... > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' > test ! -f .prettierrc.json # check prettier config is removed > cat vite.config.ts # check oxfmt config merged into vite.config.ts diff --git a/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt b/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt index 20088a9b48..e49b163037 100644 --- a/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt +++ b/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt @@ -49,15 +49,11 @@ declare module 'vite-plus' { > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt b/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt index eaf7a8b8e1..826aa133dc 100644 --- a/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt +++ b/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt @@ -44,15 +44,11 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt b/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt index 2110d21ce5..7b1e4c06c5 100644 --- a/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt +++ b/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt @@ -44,15 +44,11 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-standalone-npm/snap.txt b/packages/cli/snap-tests-global/migration-standalone-npm/snap.txt index 54f57fb5b5..8359eb19b6 100644 --- a/packages/cli/snap-tests-global/migration-standalone-npm/snap.txt +++ b/packages/cli/snap-tests-global/migration-standalone-npm/snap.txt @@ -9,13 +9,12 @@ "name": "migration-standalone-npm", "devDependencies": { "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest", + "vitest": "^4.0.0", "vite-plus": "latest" }, "packageManager": "npm@", "overrides": { - "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest" + "vite": "npm:@voidzero-dev/vite-plus-core@latest" } } diff --git a/packages/cli/snap-tests-global/migration-standalone-pnpm/snap.txt b/packages/cli/snap-tests-global/migration-standalone-pnpm/snap.txt index 93b4928ac8..c76960adbe 100644 --- a/packages/cli/snap-tests-global/migration-standalone-pnpm/snap.txt +++ b/packages/cli/snap-tests-global/migration-standalone-pnpm/snap.txt @@ -9,7 +9,7 @@ "name": "migration-standalone-pnpm", "devDependencies": { "vite": "catalog:", - "vitest": "catalog:", + "vitest": "^4.0.0", "vite-plus": "catalog:" }, "packageManager": "pnpm@" @@ -18,15 +18,11 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides, peerDependencyRules, and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-subpath/snap.txt b/packages/cli/snap-tests-global/migration-subpath/snap.txt index f68c634e75..18f766b639 100644 --- a/packages/cli/snap-tests-global/migration-subpath/snap.txt +++ b/packages/cli/snap-tests-global/migration-subpath/snap.txt @@ -38,15 +38,11 @@ core.hooksPath is not set > cat foo/pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-tsconfig-esmoduleinterop/snap.txt b/packages/cli/snap-tests-global/migration-tsconfig-esmoduleinterop/snap.txt index fbdf9b973a..9bfb9613fd 100644 --- a/packages/cli/snap-tests-global/migration-tsconfig-esmoduleinterop/snap.txt +++ b/packages/cli/snap-tests-global/migration-tsconfig-esmoduleinterop/snap.txt @@ -41,15 +41,11 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-vite-version/snap.txt b/packages/cli/snap-tests-global/migration-vite-version/snap.txt index 042250b04c..d7bf4df040 100644 --- a/packages/cli/snap-tests-global/migration-vite-version/snap.txt +++ b/packages/cli/snap-tests-global/migration-vite-version/snap.txt @@ -21,15 +21,11 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/migration-vitest-peer-dep/snap.txt b/packages/cli/snap-tests-global/migration-vitest-peer-dep/snap.txt index 588753876e..6d308e879b 100644 --- a/packages/cli/snap-tests-global/migration-vitest-peer-dep/snap.txt +++ b/packages/cli/snap-tests-global/migration-vitest-peer-dep/snap.txt @@ -24,15 +24,11 @@ > cat pnpm-workspace.yaml catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' - vitest: '*' diff --git a/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt b/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt index 0cd639acdc..96f4a2dd37 100644 --- a/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt +++ b/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt @@ -28,8 +28,7 @@ vite.config.ts "vite-plus": "catalog:" }, "overrides": { - "vite": "catalog:", - "vitest": "catalog:" + "vite": "catalog:" }, "engines": { "node": ">=22.12.0" @@ -37,7 +36,6 @@ vite.config.ts "packageManager": "bun@", "catalog": { "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest", "vite-plus": "latest" } } diff --git a/packages/cli/snap-tests-global/new-vite-monorepo/snap.txt b/packages/cli/snap-tests-global/new-vite-monorepo/snap.txt index 61de87f5c1..46b4e644ce 100644 --- a/packages/cli/snap-tests-global/new-vite-monorepo/snap.txt +++ b/packages/cli/snap-tests-global/new-vite-monorepo/snap.txt @@ -59,18 +59,14 @@ catalog: "@types/node": ^24 typescript: ^5 vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: "catalog:" - vitest: "catalog:" peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: "*" - vitest: "*" > test -f vite-plus-monorepo/.gitignore && echo '.gitignore exists' || echo 'ERROR: .gitignore missing' # verify gitignore renamed from _gitignore .gitignore exists diff --git a/packages/cli/snap-tests/command-helper/snap.txt b/packages/cli/snap-tests/command-helper/snap.txt index 4321af05fb..fc6c1d1fe7 100644 --- a/packages/cli/snap-tests/command-helper/snap.txt +++ b/packages/cli/snap-tests/command-helper/snap.txt @@ -253,11 +253,11 @@ Options: -h, --help Display this message > vp test -h # test help message -vp test/ +vitest/ WARN: no options were found for your subcommands so we printed the whole output Usage: - $ vp test [...filters] + $ vitest [...filters] Commands: run [...filters] @@ -271,16 +271,16 @@ Commands: complete [shell] For more info, run any command with the `--help` flag: - $ vp test run --help - $ vp test related --help - $ vp test watch --help - $ vp test dev --help - $ vp test bench --help - $ vp test init --help - $ vp test list --help - $ vp test --help - $ vp test complete --help - $ vp test --help --expand-help + $ vitest run --help + $ vitest related --help + $ vitest watch --help + $ vitest dev --help + $ vitest bench --help + $ vitest init --help + $ vitest list --help + $ vitest --help + $ vitest complete --help + $ vitest --help --expand-help Options: -v, --version Display version number diff --git a/packages/cli/snap-tests/create-org-bundled-monorepo/snap.txt b/packages/cli/snap-tests/create-org-bundled-monorepo/snap.txt index 3804d2905f..cc31c0c256 100644 --- a/packages/cli/snap-tests/create-org-bundled-monorepo/snap.txt +++ b/packages/cli/snap-tests/create-org-bundled-monorepo/snap.txt @@ -26,18 +26,14 @@ packages: - packages/* catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: "catalog:" - vitest: "catalog:" peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: "*" - vitest: "*" > test -d my-mono/.git && echo 'Git initialized' # git-init prompt covers bundled monorepo path Git initialized diff --git a/packages/cli/snap-tests/test-inline-snapshot-indent/snap.txt b/packages/cli/snap-tests/test-inline-snapshot-indent/snap.txt index 2fb66bcc52..1cb18f6450 100644 --- a/packages/cli/snap-tests/test-inline-snapshot-indent/snap.txt +++ b/packages/cli/snap-tests/test-inline-snapshot-indent/snap.txt @@ -1,5 +1,6 @@ > vp test run -u src/inline-snapshot.test.ts # write inline snapshot via --update (regression test for #1553) - RUN + + RUN v ✓ src/inline-snapshot.test.ts (1 test) ms diff --git a/packages/cli/snap-tests/vite-plugins-async-test/snap.txt b/packages/cli/snap-tests/vite-plugins-async-test/snap.txt index cb8596d640..cd91b5d731 100644 --- a/packages/cli/snap-tests/vite-plugins-async-test/snap.txt +++ b/packages/cli/snap-tests/vite-plugins-async-test/snap.txt @@ -1,5 +1,6 @@ > vp test # async plugins factory should load vitest plugin with configureVitest hook - RUN + + RUN v ✓ src/index.test.ts (1 test) ms diff --git a/packages/cli/snap-tests/vite-plugins-async-test/src/index.test.ts b/packages/cli/snap-tests/vite-plugins-async-test/src/index.test.ts index 7f37cab022..d6f3f94935 100644 --- a/packages/cli/snap-tests/vite-plugins-async-test/src/index.test.ts +++ b/packages/cli/snap-tests/vite-plugins-async-test/src/index.test.ts @@ -1,7 +1,7 @@ import fs from 'node:fs'; import path from 'node:path'; -import { expect, onTestFinished, test } from '@voidzero-dev/vite-plus-test'; +import { expect, onTestFinished, test } from 'vitest'; test('async plugin factory should load vitest plugin with configureVitest hook', () => { const markerPath = path.join(import.meta.dirname, '..', '.vitest-plugin-loaded'); diff --git a/packages/cli/src/__tests__/exports-map.spec.ts b/packages/cli/src/__tests__/exports-map.spec.ts new file mode 100644 index 0000000000..d4fcaa709c --- /dev/null +++ b/packages/cli/src/__tests__/exports-map.spec.ts @@ -0,0 +1,88 @@ +/** + * Regression tests for the generated package.json `exports` map. + * + * Node.js package-exports conditions are order-sensitive: when resolving + * `require('vite-plus/test/config')`, Node walks the condition object and + * picks the first matching key. `default` matches everything, so a wrongly + * ordered map like `{ types, default, require }` causes CJS consumers to + * load the ESM shim — the `.cjs` shim becomes unreachable. + * + * These tests pin the invariant that any dual-condition entry emits + * `require` BEFORE `default` and that runtime resolution returns the + * expected file extension for each consumer. + */ +import fs from 'node:fs'; +import { createRequire } from 'node:module'; +import path from 'node:path'; +import url from 'node:url'; + +import { describe, expect, it } from 'vitest'; + +const cliPkgDir = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '../..'); +const cliPkgJsonPath = path.join(cliPkgDir, 'package.json'); +const requireFromHere = createRequire(import.meta.url); + +type ExportConditions = Record; + +function isConditionObject(value: unknown): value is ExportConditions { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +describe('package.json exports map', () => { + it('every dual-condition entry emits `require` before `default`', () => { + const pkg = JSON.parse(fs.readFileSync(cliPkgJsonPath, 'utf-8')); + const exports = pkg.exports as Record; + + const offenders: Array<{ path: string; order: string[] }> = []; + + function walk(subpath: string, value: unknown) { + if (!isConditionObject(value)) { + return; + } + const keys = Object.keys(value); + const requireIdx = keys.indexOf('require'); + const defaultIdx = keys.indexOf('default'); + if (requireIdx !== -1 && defaultIdx !== -1 && requireIdx > defaultIdx) { + offenders.push({ path: subpath, order: keys }); + } + for (const [k, v] of Object.entries(value)) { + walk(`${subpath} > ${k}`, v); + } + } + + for (const [subpath, value] of Object.entries(exports)) { + walk(subpath, value); + } + + expect(offenders, 'entries with require ordered after default').toEqual([]); + }); + + it('./test/config has both `require` and `default`, with `require` first', () => { + const pkg = JSON.parse(fs.readFileSync(cliPkgJsonPath, 'utf-8')); + const entry = (pkg.exports as Record)['./test/config']; + expect(isConditionObject(entry)).toBe(true); + const keys = Object.keys(entry as ExportConditions); + expect(keys).toContain('require'); + expect(keys).toContain('default'); + expect(keys.indexOf('require')).toBeLessThan(keys.indexOf('default')); + }); + + it('`require.resolve("vite-plus/test/config")` resolves to the .cjs shim', () => { + const resolved = requireFromHere.resolve('vite-plus/test/config'); + expect(resolved.endsWith('.cjs'), `resolved to ${resolved}`).toBe(true); + }); + + it('ESM `import.meta.resolve("vite-plus/test/config")` resolves to the .js shim', () => { + // import.meta.resolve is sync in modern Node (>= 20.6) and respects the + // `default` (ESM) condition for ESM consumers. + const resolved = import.meta.resolve('vite-plus/test/config'); + expect(resolved.endsWith('.js'), `resolved to ${resolved}`).toBe(true); + }); + + it('CJS shim at ./test/config delegates to vitest/config via require()', () => { + const cfg = requireFromHere('vite-plus/test/config') as Record; + expect(cfg).toBeTypeOf('object'); + // vitest/config re-exports defineConfig / configDefaults — sanity-check one. + expect(typeof cfg.defineConfig).toBe('function'); + }); +}); diff --git a/packages/cli/src/__tests__/index.spec.ts b/packages/cli/src/__tests__/index.spec.ts index 10ff3b8a21..25de62f9a3 100644 --- a/packages/cli/src/__tests__/index.spec.ts +++ b/packages/cli/src/__tests__/index.spec.ts @@ -1,4 +1,4 @@ -import { afterEach, beforeEach, expect, test, vi } from '@voidzero-dev/vite-plus-test'; +import { afterEach, beforeEach, expect, test, vi } from 'vitest'; import { configDefaults, diff --git a/packages/cli/src/__tests__/pack.spec.ts b/packages/cli/src/__tests__/pack.spec.ts index 4ab798865c..cda2669b89 100644 --- a/packages/cli/src/__tests__/pack.spec.ts +++ b/packages/cli/src/__tests__/pack.spec.ts @@ -1,4 +1,4 @@ -import { expect, test } from '@voidzero-dev/vite-plus-test'; +import { expect, test } from 'vitest'; import { build, diff --git a/packages/cli/src/__tests__/resolve-lint.spec.ts b/packages/cli/src/__tests__/resolve-lint.spec.ts index de1c7755f9..e0b6492651 100644 --- a/packages/cli/src/__tests__/resolve-lint.spec.ts +++ b/packages/cli/src/__tests__/resolve-lint.spec.ts @@ -1,6 +1,6 @@ import { existsSync } from 'node:fs'; -import { describe, expect, it } from '@voidzero-dev/vite-plus-test'; +import { describe, expect, it } from 'vitest'; import { lint } from '../resolve-lint.js'; diff --git a/packages/cli/src/__tests__/versions.spec.ts b/packages/cli/src/__tests__/versions.spec.ts index c8ef59dd9a..c66900fe7f 100644 --- a/packages/cli/src/__tests__/versions.spec.ts +++ b/packages/cli/src/__tests__/versions.spec.ts @@ -5,15 +5,16 @@ * that syncVersionsExport() produces correct artifacts. */ import fs from 'node:fs'; +import { createRequire } from 'node:module'; import path from 'node:path'; import url from 'node:url'; -import { describe, expect, it } from '@voidzero-dev/vite-plus-test'; +import { describe, expect, it } from 'vitest'; const cliPkgDir = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '../..'); const distDir = path.join(cliPkgDir, 'dist'); const corePkgPath = path.join(cliPkgDir, '../core/package.json'); -const testPkgPath = path.join(cliPkgDir, '../test/package.json'); +const vitestPkgPath = createRequire(import.meta.url).resolve('vitest/package.json'); describe('versions export', () => { describe('build artifacts', () => { @@ -48,15 +49,13 @@ describe('versions export', () => { } }); - it('should contain all test bundledVersions', async () => { - const testPkg = JSON.parse(fs.readFileSync(testPkgPath, 'utf-8')); + it('should contain vitest version matching installed package', async () => { + const vitestPkg = JSON.parse(fs.readFileSync(vitestPkgPath, 'utf-8')); const mod = await import('../../dist/versions.js'); const versions = mod.versions as Record; - for (const [key, value] of Object.entries( - testPkg.bundledVersions as Record, - )) { - expect(versions[key], `versions.${key} should match test bundledVersions`).toBe(value); - } + expect(versions.vitest, 'versions.vitest should match installed vitest version').toBe( + vitestPkg.version, + ); }); }); diff --git a/packages/cli/src/define-config.ts b/packages/cli/src/define-config.ts index df4f333c36..e7689511cd 100644 --- a/packages/cli/src/define-config.ts +++ b/packages/cli/src/define-config.ts @@ -1,10 +1,7 @@ import type { PluginOption, UserConfig } from '@voidzero-dev/vite-plus-core'; -import { - defineConfig as viteDefineConfig, - type ConfigEnv, -} from '@voidzero-dev/vite-plus-test/config'; import type { OxfmtConfig } from 'oxfmt'; import type { OxlintConfig } from 'oxlint'; +import { defineConfig as viteDefineConfig, type ConfigEnv } from 'vitest/config'; import type { PackUserConfig } from './pack.ts'; import type { RunConfig } from './run-config.ts'; diff --git a/packages/cli/src/index.cts b/packages/cli/src/index.cts index 02f4874efb..fb19977f1b 100644 --- a/packages/cli/src/index.cts +++ b/packages/cli/src/index.cts @@ -1,6 +1,6 @@ const vite = require('@voidzero-dev/vite-plus-core'); -const vitest = require('@voidzero-dev/vite-plus-test/config'); +const vitest = require('vitest/config'); const { defineConfig, lazyPlugins } = require('./define-config'); diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 1d9d932662..6c01777f7f 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -2,6 +2,6 @@ import { defineConfig, lazyPlugins } from './define-config.ts'; export * from '@voidzero-dev/vite-plus-core'; -export * from '@voidzero-dev/vite-plus-test/config'; +export * from 'vitest/config'; export { defineConfig, lazyPlugins }; diff --git a/packages/cli/src/migration/__tests__/bun-catalog-file-protocol.spec.ts b/packages/cli/src/migration/__tests__/bun-catalog-file-protocol.spec.ts index e4050a529b..80e00bc6a1 100644 --- a/packages/cli/src/migration/__tests__/bun-catalog-file-protocol.spec.ts +++ b/packages/cli/src/migration/__tests__/bun-catalog-file-protocol.spec.ts @@ -14,9 +14,7 @@ vi.mock('../../utils/constants.js', async (importOriginal) => { VITE_PLUS_VERSION: 'file:/tmp/tgz/vite-plus-0.0.0.tgz', VITE_PLUS_OVERRIDE_PACKAGES: { vite: 'file:/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz', - vitest: 'file:/tmp/tgz/voidzero-dev-vite-plus-test-0.0.0.tgz', '@voidzero-dev/vite-plus-core': 'file:/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz', - '@voidzero-dev/vite-plus-test': 'file:/tmp/tgz/voidzero-dev-vite-plus-test-0.0.0.tgz', }, }; }); @@ -78,13 +76,11 @@ describe('rewriteMonorepo bun catalog with file: protocol', () => { // overrides should use file: paths directly, not catalog: const overrides = pkg.overrides as Record; expect(overrides.vite).toBe('file:/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz'); - expect(overrides.vitest).toBe('file:/tmp/tgz/voidzero-dev-vite-plus-test-0.0.0.tgz'); + expect(overrides.vitest).toBeUndefined(); expect(overrides['@voidzero-dev/vite-plus-core']).toBe( 'file:/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz', ); - expect(overrides['@voidzero-dev/vite-plus-test']).toBe( - 'file:/tmp/tgz/voidzero-dev-vite-plus-test-0.0.0.tgz', - ); + expect(overrides['@voidzero-dev/vite-plus-test']).toBeUndefined(); }); it('does not write file: paths into named catalogs', () => { @@ -141,7 +137,7 @@ describe('rewriteMonorepo bun catalog with file: protocol', () => { rewritePackageJson(pkg, PackageManager.pnpm, true); expect(pkg.peerDependencies.vite).toBe('^7.0.0'); - expect(pkg.peerDependencies.vitest).toBe('*'); + expect(pkg.peerDependencies.vitest).toBe('catalog:test'); expect(pkg.optionalDependencies.vite).toBe( 'file:/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz', ); diff --git a/packages/cli/src/migration/__tests__/install-failure-guard.spec.ts b/packages/cli/src/migration/__tests__/install-failure-guard.spec.ts new file mode 100644 index 0000000000..874ee16e73 --- /dev/null +++ b/packages/cli/src/migration/__tests__/install-failure-guard.spec.ts @@ -0,0 +1,77 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import { describe, expect, it } from 'vitest'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const binPath = path.resolve(__dirname, '..', 'bin.ts'); + +/** + * `runViteInstall` returns `{ status: 'failed', exitCode }` (it does not throw) + * when the install process exits non-zero. Earlier versions of `migration/bin.ts` + * only summed `installSummary.durationMs` and reported success regardless of + * `status`, which left the project's `node_modules` desynced from a freshly + * mutated `package.json` (network/auth failures, registry blips, pnpm lockfile + * conflicts after override resolution) while still printing + * "Dependencies installed" to the user. + * + * Two install sites need this handling: + * 1. The full migration path (`executeMigrationPlan`'s final reinstall, run + * AFTER manifest/source rewrites land). + * 2. The early-return path (`main` when `vite-plus` is already a dep but a + * stale-wrapper repair or ESLint/Prettier migration touches package.json). + * + * Both paths must funnel install results through `handleInstallResult` so that + * failures warn the user, append to `report.warnings`, and flip + * `process.exitCode`. This is a guard test — if a future refactor drops the + * helper or stops calling it from either path, this fails loudly so reviewers + * can re-evaluate the install-failure UX before it ships. + */ +describe('migration install failure handling', () => { + const binSource = fs.readFileSync(binPath, 'utf8'); + + describe('handleInstallResult helper', () => { + it('defines a `handleInstallResult` function in bin.ts', () => { + expect(binSource).toMatch(/function handleInstallResult\s*\(/); + }); + + it('branches on `installSummary.status === "installed"` and credits duration', () => { + expect(binSource).toMatch(/installSummary\.status === 'installed'/); + expect(binSource).toMatch(/return installSummary\.durationMs/); + }); + + it('branches on `installSummary.status === "failed"` and warns + flips exitCode', () => { + expect(binSource).toMatch(/installSummary\.status === 'failed'/); + expect(binSource).toMatch(/warnMsg\(/); + expect(binSource).toMatch(/report\.warnings\.push\(/); + expect(binSource).toMatch(/process\.exitCode\s*=/); + }); + }); + + describe('full migration path (executeMigrationPlan)', () => { + it('reconciles `finalInstallSummary` through `handleInstallResult`', () => { + // The full-path final reinstall must run through the helper so a failed + // install after manifest/source rewrites does not silently report a + // desynced project as a successful migration. + expect(binSource).toMatch(/finalInstallSummary[\s\S]{0,1500}handleInstallResult\(/); + }); + + it('does NOT add `finalInstallSummary.durationMs` directly to the return value', () => { + // The buggy round-7 version returned + // `initialInstallSummary.durationMs + finalInstallSummary.durationMs` + // unconditionally. The fix routes `finalInstallSummary` through the + // helper which returns 0 on failure. Catch any regression that re-adds + // the raw `.durationMs` access. + expect(binSource).not.toMatch(/finalInstallSummary\.durationMs/); + }); + }); + + describe('early-return path (main, hasVitePlusDependency branch)', () => { + it('reconciles `installSummary` through `handleInstallResult`', () => { + expect(binSource).toMatch( + /const installSummary = await runViteInstall\([\s\S]{0,1500}handleInstallResult\(/, + ); + }); + }); +}); diff --git a/packages/cli/src/migration/__tests__/migrator.spec.ts b/packages/cli/src/migration/__tests__/migrator.spec.ts index 45b094caa7..3125f31154 100644 --- a/packages/cli/src/migration/__tests__/migrator.spec.ts +++ b/packages/cli/src/migration/__tests__/migrator.spec.ts @@ -170,7 +170,9 @@ describe('rewritePackageJson', () => { rewritePackageJson(pkg, PackageManager.yarn, true); expect(pkg.devDependencies.vite).toBe('catalog:'); - expect(pkg.dependencies.vitest).toBe('catalog:'); + // vitest is no longer aliased to @voidzero-dev/vite-plus-test; it's left + // untouched so users can keep upstream vitest pinned independently. + expect(pkg.dependencies.vitest).toBe('^4.0.0'); expect((pkg.devDependencies as Record)['vite-plus']).toBe('catalog:'); }); @@ -189,7 +191,8 @@ describe('rewritePackageJson', () => { expect(pkg.devDependencies.vite).toBe('catalog:'); expect(pkg.optionalDependencies.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); - expect(pkg.optionalDependencies.vitest).toBe('npm:@voidzero-dev/vite-plus-test@latest'); + // vitest is no longer aliased — the catalog: spec is preserved as-is. + expect(pkg.optionalDependencies.vitest).toBe('catalog:test'); expect((pkg.devDependencies as Record)['vite-plus']).toBe('catalog:'); }); @@ -653,7 +656,9 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { const overrides = pnpm.overrides as Record; expect(overrides['some-pkg']).toBe('1.0.0'); expect(overrides.vite).toBeDefined(); - expect(overrides.vitest).toBeDefined(); + // vitest is no longer injected into overrides — upstream vitest is consumed + // transitively via vite-plus. + expect(overrides.vitest).toBeUndefined(); // peerDependencyRules should be present expect(pnpm.peerDependencyRules).toBeDefined(); @@ -683,8 +688,9 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { const pkg = readJson(path.join(tmpDir, 'package.json')); const pnpm = pkg.pnpm as Record; const rules = pnpm.peerDependencyRules as Record; - // Custom entries preserved, Vite entries merged - expect(rules.allowAny).toEqual(expect.arrayContaining(['react', 'vite', 'vitest'])); + // Custom entries preserved, Vite entries merged (vitest is no longer + // injected as it's not a managed override key anymore). + expect(rules.allowAny).toEqual(expect.arrayContaining(['react', 'vite'])); // ignoreMissing preserved expect(rules.ignoreMissing).toEqual(['@types/node']); }); @@ -698,7 +704,8 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { const yaml = readYaml(path.join(tmpDir, 'pnpm-workspace.yaml')); expect(yaml).toContain("vite: 'catalog:'"); - expect(yaml).toContain("vitest: 'catalog:'"); + // vitest is no longer added to overrides — only `vite` is the managed key. + expect(yaml).not.toContain('vitest:'); }); it('rewrites named catalogs in pnpm-workspace.yaml without adding new entries', () => { @@ -741,12 +748,14 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { catalogs: Record>; }; expect(yaml.overrides.vite).toBe('catalog:vite7'); - expect(yaml.overrides.vitest).toBe('catalog:'); - expect(yaml.catalog.vitest).toBe('npm:@voidzero-dev/vite-plus-test@latest'); + // vitest is no longer a managed override / aliased catalog entry — pre-existing + // user-defined catalog entries are preserved verbatim. + expect(yaml.overrides.vitest).toBeUndefined(); + expect(yaml.catalog.vitest).toBe('^4.0.0'); expect(yaml.catalogs.vite7.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); expect(yaml.catalogs.vite7.react).toBe('^18.0.0'); expect(yaml.catalogs.vite7['vite-plus']).toBe('latest'); - expect(yaml.catalogs.test.vitest).toBe('npm:@voidzero-dev/vite-plus-test@latest'); + expect(yaml.catalogs.test.vitest).toBe('^4.0.0'); expect(yaml.catalogs.test.tsdown).toBeUndefined(); expect(yaml.catalogs.test['vite-plus']).toBeUndefined(); @@ -757,7 +766,8 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { expect(pkg.devDependencies.vite).toBe('catalog:vite7'); expect(pkg.devDependencies['vite-plus']).toBe('catalog:'); expect(pkg.peerDependencies.vite).toBe('^7.0.0'); - expect(pkg.peerDependencies.vitest).toBe('^4.0.0'); + // vitest peer dep is left untouched (no override → no resolution from catalog). + expect(pkg.peerDependencies.vitest).toBe('catalog:'); expect(pkg.peerDependencies).not.toHaveProperty('tsdown'); }); @@ -788,7 +798,8 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { catalogs: Record>; }; expect(yaml.overrides.vite).toBe('catalog:vite7'); - expect(yaml.overrides.vitest).toBe('catalog:'); + // vitest is no longer injected into overrides. + expect(yaml.overrides.vitest).toBeUndefined(); expect(yaml.overrides.react).toBe('^18.0.0'); expect(yaml.catalogs.vite7.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); @@ -832,7 +843,8 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { overrides: Record; }; expect(yaml.overrides.vite).toBe('catalog:'); - expect(yaml.overrides.vitest).toBe('catalog:'); + // vitest is no longer added to overrides. + expect(yaml.overrides.vitest).toBeUndefined(); }); it('does not resolve peer dependency catalog specs to migrated aliases', () => { @@ -864,7 +876,8 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { peerDependencies: Record; }; expect(pkg.peerDependencies.vite).toBe('*'); - expect(pkg.peerDependencies.vitest).toBe('*'); + // vitest peer dep is no longer coerced to '*' — vitest isn't a managed key. + expect(pkg.peerDependencies.vitest).toBe('catalog:'); }); }); @@ -913,7 +926,8 @@ describe('rewriteMonorepo yarn catalog', () => { expect(yarnrc.nodeLinker).toBe('node-modules'); expect(yarnrc.catalogs.vite7.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); expect(yarnrc.catalogs.vite7.react).toBe('^18.0.0'); - expect(yarnrc.catalogs.test.vitest).toBe('npm:@voidzero-dev/vite-plus-test@latest'); + // vitest is no longer aliased — its catalog entry is left as the user wrote it. + expect(yarnrc.catalogs.test.vitest).toBe('^4.0.0'); expect(yarnrc.catalogs.test.oxlint).toBeUndefined(); const pkg = readJson(path.join(tmpDir, 'package.json')) as { @@ -922,7 +936,8 @@ describe('rewriteMonorepo yarn catalog', () => { }; expect(pkg.devDependencies.vite).toBe('catalog:vite7'); expect(pkg.peerDependencies.vite).toBe('^7.0.0'); - expect(pkg.peerDependencies.vitest).toBe('^4.0.0'); + // vitest peer catalog: ref is preserved as-is (no longer treated as a managed override). + expect(pkg.peerDependencies.vitest).toBe('catalog:test'); }); }); @@ -1015,7 +1030,8 @@ describe('rewriteMonorepo bun catalog', () => { expect(pkg.workspaces.catalog.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); expect(pkg.workspaces.catalog['vite-plus']).toBe('latest'); expect(pkg.catalog.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); - expect(pkg.catalog.vitest).toBe('npm:@voidzero-dev/vite-plus-test@latest'); + // vitest is no longer aliased — pre-existing catalog entries are kept as-is. + expect(pkg.catalog.vitest).toBe('^3.0.0'); expect(pkg.catalog.tsdown).toBeUndefined(); expect(pkg.catalog.react).toBe('^19.0.0'); expect(pkg.catalog['vite-plus']).toBeUndefined(); @@ -1075,12 +1091,14 @@ describe('rewriteMonorepo bun catalog', () => { expect(pkg.catalogs.build.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); expect(pkg.catalogs.build.react).toBe('^19.0.0'); expect(pkg.catalogs.build.tsdown).toBeUndefined(); - expect(pkg.catalogs.test.vitest).toBe('npm:@voidzero-dev/vite-plus-test@latest'); + // vitest catalog entries and overrides are not synthesized anymore. + expect(pkg.catalogs.test.vitest).toBe('^4.0.0'); expect(pkg.overrides.vite).toBe('catalog:build'); - expect(pkg.overrides.vitest).toBe('catalog:'); + expect(pkg.overrides.vitest).toBeUndefined(); expect(pkg.devDependencies.vite).toBe('catalog:build'); expect(pkg.peerDependencies.vite).toBe('^7.0.0'); - expect(pkg.peerDependencies.vitest).toBe('^4.0.0'); + // vitest peer catalog: ref is preserved as-is. + expect(pkg.peerDependencies.vitest).toBe('catalog:test'); }); it('rewrites workspaces named catalogs and writes default catalog beside them', () => { @@ -1115,7 +1133,8 @@ describe('rewriteMonorepo bun catalog', () => { expect(pkg.workspaces.catalog['vite-plus']).toBe('latest'); expect(pkg.workspaces.catalogs.build.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); expect(pkg.workspaces.catalogs.build.oxlint).toBeUndefined(); - expect(pkg.workspaces.catalogs.test.vitest).toBe('npm:@voidzero-dev/vite-plus-test@latest'); + // vitest catalog entries are preserved verbatim, not aliased. + expect(pkg.workspaces.catalogs.test.vitest).toBe('^4.0.0'); expect(pkg.workspaces.catalogs.test.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); expect(pkg.overrides.vite).toBe('catalog:'); }); diff --git a/packages/cli/src/migration/bin.ts b/packages/cli/src/migration/bin.ts index 925519421a..55d0dd8618 100644 --- a/packages/cli/src/migration/bin.ts +++ b/packages/cli/src/migration/bin.ts @@ -29,6 +29,7 @@ import { hasVitePlusDependency, readNearestPackageJson } from '../utils/package. import { displayRelative } from '../utils/path.ts'; import { cancelAndExit, + type CommandRunSummary, defaultInteractive, downloadPackageManager, promptGitHooks, @@ -36,7 +37,7 @@ import { selectPackageManager, upgradeYarn, } from '../utils/prompts.ts'; -import { accent, log, muted, printHeader } from '../utils/terminal.ts'; +import { accent, log, muted, printHeader, warnMsg } from '../utils/terminal.ts'; import type { PackageDependencies } from '../utils/types.ts'; import { detectWorkspace } from '../utils/workspace.ts'; import { @@ -459,6 +460,34 @@ function formatDuration(durationMs: number) { return `${Math.round(durationSeconds)}s`; } +/** + * Reconcile a CommandRunSummary from `runViteInstall` with the migration's + * duration counter and exit-code state. `runViteInstall` returns + * `{ status: 'failed', exitCode }` without throwing; treating that as a success + * (incrementing duration unconditionally) would let the migration claim + * "Dependencies installed" while node_modules is desynced from the just-mutated + * package.json. This helper centralizes the right handling: credit duration on + * success, warn + flip exitCode on failure, stay silent on skip. + */ +function handleInstallResult( + installSummary: CommandRunSummary, + rootDir: string, + report: MigrationReport, +): number { + if (installSummary.status === 'installed') { + return installSummary.durationMs; + } + if (installSummary.status === 'failed') { + const exitCode = installSummary.exitCode ?? 1; + const message = `Dependency installation failed (exit code ${exitCode}). Run \`vp install\` manually in ${rootDir} to resync node_modules.`; + warnMsg(message); + report.warnings.push(message); + process.exitCode = exitCode; + return 0; + } + return 0; +} + function showMigrationSummary(options: { projectRoot: string; packageManager: string; @@ -788,8 +817,15 @@ async function executeMigrationPlan( ); clearMigrationProgress(); + const finalInstallDurationMs = handleInstallResult( + finalInstallSummary, + workspaceInfo.rootDir, + report, + ); return { - installDurationMs: initialInstallSummary.durationMs + finalInstallSummary.durationMs, + installDurationMs: + handleInstallResult(initialInstallSummary, workspaceInfo.rootDir, report) + + finalInstallDurationMs, packageManagerVersion: downloadResult.version, report, }; @@ -900,7 +936,11 @@ async function main() { packageManagerVersion: resolvedVersion, }, ); - installDurationMs += installSummary.durationMs; + installDurationMs += handleInstallResult( + installSummary, + workspaceInfoOptional.rootDir, + report, + ); didMigrate = true; report.eslintMigrated = eslintMigrated; report.prettierMigrated = prettierMigrated; diff --git a/packages/cli/src/migration/migrator.ts b/packages/cli/src/migration/migrator.ts index a771fbe7e3..1b8bb84e76 100644 --- a/packages/cli/src/migration/migrator.ts +++ b/packages/cli/src/migration/migrator.ts @@ -98,6 +98,54 @@ const PUBLIC_PEER_DEPENDENCY_FALLBACKS: Record = { vitest: '*', }; +// Legacy wrapper package names that may appear as the target of override +// aliases left over from earlier vite-plus migrations. `@voidzero-dev/vite-plus-test` +// was deleted; any catalog/override entry still pointing at it is stale. +const LEGACY_WRAPPER_PACKAGE_NAMES = ['@voidzero-dev/vite-plus-test'] as const; + +// Fallback specs used when normalizing a stale wrapper alias. Real user +// ranges (e.g. `vitest: ^3.0.0`) are preserved — only the wrapper alias is +// rewritten. For `vitest`, we substitute the vitest version vite-plus +// bundles so any `catalog:` reference the user still has resolves cleanly. +const LEGACY_WRAPPER_FALLBACK_VERSIONS: Record = { + vitest: '^4.1.5', +}; + +function isLegacyWrapperSpec(value: string | undefined): boolean { + if (!value) { + return false; + } + for (const name of LEGACY_WRAPPER_PACKAGE_NAMES) { + if (value === `npm:${name}` || value.startsWith(`npm:${name}@`)) { + return true; + } + } + return false; +} + +/** + * Rewrite or remove keys whose value points at a deleted vite-plus wrapper. + * When a fallback exists for the key (e.g. `vitest`), the value is replaced + * so existing `catalog:` references continue to resolve. Otherwise the key + * is dropped entirely. Returns true iff any entry was changed. + */ +function pruneLegacyWrapperAliases(record: Record | undefined): boolean { + if (!record) return false; + let mutated = false; + for (const key of Object.keys(record)) { + if (isLegacyWrapperSpec(record[key])) { + const fallback = LEGACY_WRAPPER_FALLBACK_VERSIONS[key]; + if (fallback !== undefined) { + record[key] = fallback; + } else { + delete record[key]; + } + mutated = true; + } + } + return mutated; +} + type PackageJsonDependencyField = | 'devDependencies' | 'dependencies' @@ -856,6 +904,11 @@ export function rewriteStandaloneProject( }; }; }>(packageJsonPath, (pkg) => { + // Strip stale `vite-plus-test` wrapper aliases before injecting new overrides + // so the deleted wrapper doesn't survive migration in any sink. + pruneLegacyWrapperAliases(pkg.resolutions); + pruneLegacyWrapperAliases(pkg.overrides); + pruneLegacyWrapperAliases(pkg.pnpm?.overrides); if (packageManager === PackageManager.yarn) { pkg.resolutions = { ...pkg.resolutions, @@ -1100,6 +1153,7 @@ function rewritePnpmWorkspaceYaml(projectPath: string): void { // overrides const overrides = doc.getIn(['overrides']); + pruneYamlMapLegacyWrapperAliases(overrides); for (const key of Object.keys(VITE_PLUS_OVERRIDE_PACKAGES)) { const currentVersion = getYamlMapScalarStringValue(overrides, key); const version = getCatalogDependencySpec( @@ -1427,6 +1481,27 @@ function getYamlMapScalarStringValue(map: unknown, key: string): string | undefi return undefined; } +function pruneYamlMapLegacyWrapperAliases(map: unknown): void { + if (!(map instanceof YAMLMap)) return; + const stale: Array<{ key: Scalar; fallback: string | undefined }> = []; + for (const item of map.items) { + const value = item.value instanceof Scalar ? item.value.value : undefined; + if (typeof value === 'string' && isLegacyWrapperSpec(value) && item.key instanceof Scalar) { + stale.push({ + key: item.key, + fallback: LEGACY_WRAPPER_FALLBACK_VERSIONS[item.key.value], + }); + } + } + for (const { key, fallback } of stale) { + if (fallback !== undefined) { + map.set(key, scalarString(fallback)); + } else { + map.delete(key); + } + } +} + function rewriteCatalog(doc: YamlDocument): void { for (const [key, value] of Object.entries(VITE_PLUS_OVERRIDE_PACKAGES)) { // ERR_PNPM_CATALOG_IN_OVERRIDES  Could not resolve a catalog in the overrides: The entry for 'vite' in catalog 'default' declares a dependency using the 'file' protocol @@ -1445,6 +1520,8 @@ function rewriteCatalog(doc: YamlDocument): void { doc.deleteIn(path); } } + // Drop any entry still pointing at the deleted `vite-plus-test` wrapper. + pruneYamlMapLegacyWrapperAliases(doc.getIn(['catalog'])); const catalogs = doc.getIn(['catalogs']); if (!(catalogs instanceof YAMLMap)) { @@ -1471,6 +1548,7 @@ function rewriteCatalog(doc: YamlDocument): void { doc.deleteIn(catalogPath); } } + pruneYamlMapLegacyWrapperAliases(item.value); } } @@ -1524,27 +1602,37 @@ function rewriteBunCatalog(projectPath: string): void { }; rewriteCatalogObject(catalog, true); + pruneLegacyWrapperAliases(catalog); if (useWorkspacesCatalog) { workspacesObj.catalog = catalog; if (pkg.catalog) { rewriteCatalogObject(pkg.catalog, false); + pruneLegacyWrapperAliases(pkg.catalog); } } else { pkg.catalog = catalog; if (workspacesObj?.catalog) { rewriteCatalogObject(workspacesObj.catalog, false); + pruneLegacyWrapperAliases(workspacesObj.catalog); } } if (workspacesObj?.catalogs) { rewriteCatalogsObject(workspacesObj.catalogs); + for (const named of Object.values(workspacesObj.catalogs)) { + pruneLegacyWrapperAliases(named); + } } if (pkg.catalogs) { rewriteCatalogsObject(pkg.catalogs); + for (const named of Object.values(pkg.catalogs)) { + pruneLegacyWrapperAliases(named); + } } // bun overrides support catalog: references const overrides: Record = { ...pkg.overrides }; + pruneLegacyWrapperAliases(overrides); for (const [key, value] of Object.entries(VITE_PLUS_OVERRIDE_PACKAGES)) { overrides[key] = getCatalogDependencySpec(overrides[key], value, true); } @@ -1731,6 +1819,14 @@ export function rewritePackageJson( { dependencyField: 'peerDependencies', dependencies: pkg.peerDependencies }, { dependencyField: 'optionalDependencies', dependencies: pkg.optionalDependencies }, ]; + // Scrub stale `npm:@voidzero-dev/vite-plus-test@...` aliases left over from + // earlier vite-plus migrations — the wrapper package no longer exists, so + // these entries would break `pnpm install`. Real user ranges are preserved. + for (const { dependencies } of dependencyGroups) { + if (pruneLegacyWrapperAliases(dependencies)) { + needVitePlus = true; + } + } for (const [key, version] of Object.entries(VITE_PLUS_OVERRIDE_PACKAGES)) { for (const { dependencyField, dependencies } of dependencyGroups) { if (dependencies?.[key]) { @@ -1770,6 +1866,23 @@ export function rewritePackageJson( pkg.devDependencies[peerDep] = '*'; } } + // Trigger vite-plus install when a project has a vitest-adjacent package + // (e.g. `vitest-browser-svelte`) that declares vitest as a peer dep — even + // if the project has no vite/oxlint/tsdown dep to migrate. The peer dep is + // satisfied by the upstream vitest that vite-plus bundles as a direct dep. + // Note: peerDependencies count as "adjacent signal" but NOT as installed. + const installableNames = [ + ...Object.keys(pkg.dependencies ?? {}), + ...Object.keys(pkg.devDependencies ?? {}), + ...Object.keys(pkg.optionalDependencies ?? {}), + ]; + const adjacentSignals = [...installableNames, ...Object.keys(pkg.peerDependencies ?? {})]; + const isVitestAdjacent = + !installableNames.includes('vitest') && + adjacentSignals.some((name) => name !== 'vitest' && name.includes('vitest')); + if (isVitestAdjacent) { + needVitePlus = true; + } if (needVitePlus) { // add vite-plus to devDependencies const version = @@ -1778,10 +1891,13 @@ export function rewritePackageJson( ...pkg.devDependencies, [VITE_PLUS_NAME]: version, }; - // Add vitest to devDependencies when a remaining dependency likely peer-depends - // on vitest (e.g., vitest-browser-svelte). Without this, pnpm resolves the real - // vitest for peer deps instead of @voidzero-dev/vite-plus-test, causing - // third-party type augmentations to target the wrong module. + // Add vitest to devDependencies when a remaining dependency likely + // peer-depends on vitest (e.g., vitest-browser-svelte). Vite-plus already + // bundles upstream vitest 4.1.5 as a direct dep, so the runtime resolution + // works without this — but strict pnpm / yarn-PnP refuse to expose a + // transitive `vitest` to satisfy a peer dep declared by a different + // direct dep. Adding `vitest` to the user's devDependencies pins the + // peer-dep target to the same upstream version vite-plus ships with. const installableDeps = { ...pkg.dependencies, ...pkg.devDependencies, @@ -1791,8 +1907,7 @@ export function rewritePackageJson( !installableDeps.vitest && Object.keys(installableDeps).some((name) => name.includes('vitest')) ) { - const ver = VITE_PLUS_OVERRIDE_PACKAGES.vitest; - pkg.devDependencies.vitest = getCatalogDependencySpec(undefined, ver, supportCatalog); + pkg.devDependencies.vitest = getCatalogDependencySpec(undefined, '4.1.5', supportCatalog); } } return extractedStagedConfig; diff --git a/packages/cli/src/resolve-test.ts b/packages/cli/src/resolve-test.ts index 8c547c8d3a..a00c216285 100644 --- a/packages/cli/src/resolve-test.ts +++ b/packages/cli/src/resolve-test.ts @@ -2,16 +2,23 @@ * Vitest tool resolver for the vite-plus CLI. * * This module exports a function that resolves the Vitest binary path - * to the bundled Vitest in the CLI distribution. The resolved path is - * passed back to the Rust core, which then executes Vitest for running tests. + * to the vitest package installed alongside the CLI (or in the user's + * project, resolved from the current working directory first). The + * resolved path is passed back to the Rust core, which then executes + * Vitest for running tests. * * Used for: `vite-plus test` command */ +import { readFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { DEFAULT_ENVS, resolve } from './utils/constants.ts'; +interface VitestPackageJson { + bin?: string | Record; +} + /** * Resolves the Vitest binary path and environment variables. * @@ -21,13 +28,21 @@ import { DEFAULT_ENVS, resolve } from './utils/constants.ts'; * * Vitest is Vite's testing framework that provides a Jest-compatible * testing experience with Vite's fast HMR and transformation pipeline. - * The function points to the bundled Vitest in the CLI's dist directory. + * The function resolves vitest from the user's project first, falling + * back to the copy installed alongside the CLI. */ export async function test(): Promise<{ binPath: string; envs: Record; }> { - const binPath = join(dirname(resolve('@voidzero-dev/vite-plus-test')), 'dist', 'cli.js'); + const pkgJsonPath = resolve('vitest/package.json'); + const pkgRoot = dirname(pkgJsonPath); + const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8')) as VitestPackageJson; + const binRel = typeof pkgJson.bin === 'string' ? pkgJson.bin : pkgJson.bin?.vitest; + if (!binRel) { + throw new Error(`Could not find 'vitest' bin entry in ${pkgJsonPath}`); + } + const binPath = join(pkgRoot, binRel); return { binPath, diff --git a/packages/cli/src/utils/constants.ts b/packages/cli/src/utils/constants.ts index 137416b2b9..9613514273 100644 --- a/packages/cli/src/utils/constants.ts +++ b/packages/cli/src/utils/constants.ts @@ -7,7 +7,6 @@ export const VITE_PLUS_OVERRIDE_PACKAGES: Record = process.env.V ? JSON.parse(process.env.VP_OVERRIDE_PACKAGES) : { vite: 'npm:@voidzero-dev/vite-plus-core@latest', - vitest: 'npm:@voidzero-dev/vite-plus-test@latest', }; /** diff --git a/packages/test/.gitignore b/packages/test/.gitignore deleted file mode 100644 index 7f727e288b..0000000000 --- a/packages/test/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.d.ts -*.d.cts -/LICENSE -LICENSE.md -*.cjs -*.mjs -browser/ -dist/ diff --git a/packages/test/BUNDLING.md b/packages/test/BUNDLING.md deleted file mode 100644 index 4866da58e1..0000000000 --- a/packages/test/BUNDLING.md +++ /dev/null @@ -1,427 +0,0 @@ -# Test Package Bundling Architecture - -This document explains how `@voidzero-dev/vite-plus-test` bundles vitest and its dependencies. - -## Overview - -The test package uses a **hybrid bundling strategy**: - -1. **COPY** all `@vitest/*` packages (preserves browser/Node.js separation) -2. **BUNDLE** only leaf dependencies like `chai`, `pathe` (reduces install size) -3. **Separate entries** (`index.js` vs `index-node.js`) prevent Node.js code from loading in browsers - -This approach avoids the critical issue of Rolldown creating shared chunks that mix Node.js-only code (like `__vite__injectQuery`) with browser code, which causes runtime crashes. - -## Dependencies Classification - -### Copied Packages (`dist/@vitest/`) - -These 11 `@vitest/*` packages are **copied** (not bundled) to preserve their original file structure: - -| Package | Purpose | -| ----------------------------- | ---------------------------------------------------- | -| `@vitest/runner` | Test runner core | -| `@vitest/utils` | Utilities (source-map, error, display, timers, etc.) | -| `@vitest/spy` | Spy/mock implementation | -| `@vitest/expect` | Assertion library | -| `@vitest/snapshot` | Snapshot testing | -| `@vitest/mocker` | Module mocking (node, browser, automock) | -| `@vitest/pretty-format` | Output formatting | -| `@vitest/browser` | Browser testing support | -| `@vitest/browser-playwright` | Playwright integration | -| `@vitest/browser-webdriverio` | WebdriverIO integration | -| `@vitest/browser-preview` | Preview (testing-library) integration | - -**Why copy instead of bundle?** Bundling would create shared chunks that mix browser-safe and Node.js-only code. Copying preserves the original separation. - -### Bundled Leaf Dependencies (`dist/vendor/`) - -These packages are bundled using Rolldown into `dist/vendor/*.mjs`: - -| Package | Purpose | -| --------------------- | ----------------------------------- | -| `chai` | Assertion library (core of expect) | -| `pathe` | Path utilities | -| `tinyrainbow` | Terminal colors | -| `magic-string` | String manipulation for source maps | -| `estree-walker` | AST traversal | -| `why-is-node-running` | Debug tool for hanging processes | - -These were moved from `dependencies` to `devDependencies` since they're bundled. - -### Runtime Dependencies (NOT Bundled) - -These remain in `dependencies` and are installed with the package: - -| Package | Reason Not Bundled | -| ----------------- | --------------------------------------------- | -| `sirv` | Static file server - complex runtime behavior | -| `ws` | WebSocket server - native bindings | -| `pixelmatch` | Image comparison - optional feature | -| `pngjs` | PNG handling - optional feature | -| `es-module-lexer` | ESM parsing - small, used at runtime | -| `expect-type` | Type testing - small | -| `obug` | Debugging - small | -| `picomatch` | Glob matching - small | -| `std-env` | Environment detection - small | -| `tinybench` | Benchmarking - optional feature | -| `tinyexec` | Command execution - small | -| `tinyglobby` | File globbing - small | - -### External Blocklist (Must NOT Bundle) - -These packages are explicitly kept external in `EXTERNAL_BLOCKLIST` during the Rolldown build: - -| Package | Reason | -| ----------------------- | ----------------------------------------- | -| `playwright` | Native bindings, user must install | -| `webdriverio` | Native bindings, user must install | -| `debug` | Environment detection breaks when bundled | -| `happy-dom` | Optional peer dependency | -| `jsdom` | Optional peer dependency | -| `@edge-runtime/vm` | Optional peer dependency | -| `@standard-schema/spec` | Types-only import from @vitest/expect | -| `msw`, `msw/*` | Optional peer dependency for mocking | - -### Browser Plugin Exclude List - -Additionally, these packages are added to the **browser plugin's exclude list** (in `patchVitestBrowserPackage`), which prevents Vite's optimizer from bundling them during browser tests: - -| Package | Reason | -| --------------------- | ------------------------------------------------ | -| `lightningcss` | Native bindings | -| `@tailwindcss/oxide` | Native bindings | -| `tailwindcss` | Pulls in @tailwindcss/oxide | -| `@vitest/browser` | Needs vendor-aliases plugin resolution | -| `@vitest/ui` | Optional peer dependency | -| `@vitest/mocker/node` | Imports @voidzero-dev/vite-plus-core (Node-only) | - -This is a different mechanism than `EXTERNAL_BLOCKLIST` - it controls runtime optimization, not build-time bundling. - ---- - -## Migration Guide - -For maintainers developing the vitest/vite migration feature, here are the transformations needed. - -### Import Rewrites - -| Original Import | Rewritten Import | -| ------------------------------------ | --------------------------------------------------------- | -| `from "@vitest/browser-playwright"` | `from "@voidzero-dev/vite-plus-test/browser-playwright"` | -| `from "@vitest/browser-webdriverio"` | `from "@voidzero-dev/vite-plus-test/browser-webdriverio"` | -| `from "@vitest/browser-preview"` | `from "@voidzero-dev/vite-plus-test/browser-preview"` | -| `from "vite"` | `from "@voidzero-dev/vite-plus-core"` | -| `from "vite/module-runner"` | `from "@voidzero-dev/vite-plus-core/module-runner"` | -| `import('vitest')` | `import('@voidzero-dev/vite-plus-test')` | - -**Note**: `@voidzero-dev/vite-plus-core` is the bundled version of upstream vite (Vite v8 beta). See [Core Package Bundling](../core/BUNDLING.md) for details on what it contains. - -**Note**: The `import('vitest')` → `import('@voidzero-dev/vite-plus-test')` rewrite is critical for `globals.d.ts`, which declares global types like `typeof import('vitest')['test']`. Without this rewrite, `vitest` is not resolvable from the `@voidzero-dev/vite-plus-test` package context in pnpm's strict `node_modules` layout. TypeScript silently treats unresolved dynamic type imports as `any`, but oxlint's type-aware linting treats them as `error` types, causing `no-unsafe-call` errors. The rewrite turns this into a self-reference that resolves correctly via Node.js package self-referencing. - -**Note:** When using pnpm overrides, you have three options for browser provider imports: - -- `vitest/browser-playwright` (or `vitest/browser-webdriverio`, `vitest/browser-preview`) - works when `vitest` is overridden to our package (Recommended) -- `@voidzero-dev/vite-plus-test/browser-playwright` - direct import from test package -- `vite-plus/test/plugins/browser-playwright` - direct import from CLI package - -Importing from `@vitest/browser-*` packages directly requires additional overrides for those specific packages. - -### package.json Changes - -**Remove these devDependencies** (now bundled): - -```json -{ - "devDependencies": { - "@vitest/browser": "...", // Remove - "@vitest/browser-playwright": "...", // Remove (if using playwright) - "@vitest/browser-webdriverio": "...", // Remove (if using webdriverio) - "@vitest/browser-preview": "...", // Remove (if using testing-library) - "@vitest/ui": "..." // Remove (peer dep, not bundled but optional) - } -} -``` - -**Add pnpm overrides**: - -```yaml -# pnpm-workspace.yaml -overrides: - vite: 'file:path/to/vite-plus-core.tgz' - vitest: 'file:path/to/vite-plus-test.tgz' - '@vitest/browser': 'file:path/to/vite-plus-test.tgz' - '@vitest/browser-playwright': 'file:path/to/vite-plus-test.tgz' - '@vitest/browser-webdriverio': 'file:path/to/vite-plus-test.tgz' - '@vitest/browser-preview': 'file:path/to/vite-plus-test.tgz' -``` - -Or using npm package names: - -```yaml -overrides: - vite: 'npm:@voidzero-dev/vite-plus-core' - vitest: 'npm:@voidzero-dev/vite-plus-test' - '@vitest/browser': 'npm:@voidzero-dev/vite-plus-test' - '@vitest/browser-playwright': 'npm:@voidzero-dev/vite-plus-test' - '@vitest/browser-webdriverio': 'npm:@voidzero-dev/vite-plus-test' - '@vitest/browser-preview': 'npm:@voidzero-dev/vite-plus-test' -``` - -### Config File Updates - -```typescript -// Before (playwright) -import { playwright } from '@vitest/browser-playwright'; - -// After - Option 1 (Recommended): Via vitest subpath (works when vitest is overridden) -import { playwright } from 'vitest/browser-playwright'; - -// After - Option 2: Direct import from test package -import { playwright } from '@voidzero-dev/vite-plus-test/browser-playwright'; - -// After - Option 3: Direct import from CLI package -import { playwright } from 'vite-plus/test/plugins/browser-playwright'; -``` - -Similarly for WebdriverIO: - -```typescript -import { webdriverio } from 'vitest/browser-webdriverio'; -``` - -And for Preview (testing-library): - -```typescript -import { preview } from 'vitest/browser-preview'; -``` - -### Plugin Exports for pnpm Overrides - -The package provides `./plugins/*` exports to enable pnpm overrides for all `@vitest/*` packages: - -``` -@vitest/runner -> @voidzero-dev/vite-plus-test/plugins/runner -@vitest/utils -> @voidzero-dev/vite-plus-test/plugins/utils -@vitest/utils/error -> @voidzero-dev/vite-plus-test/plugins/utils-error -@vitest/spy -> @voidzero-dev/vite-plus-test/plugins/spy -@vitest/expect -> @voidzero-dev/vite-plus-test/plugins/expect -@vitest/snapshot -> @voidzero-dev/vite-plus-test/plugins/snapshot -@vitest/mocker -> @voidzero-dev/vite-plus-test/plugins/mocker -@vitest/pretty-format -> @voidzero-dev/vite-plus-test/plugins/pretty-format -@vitest/browser -> @voidzero-dev/vite-plus-test/plugins/browser -@vitest/browser-playwright -> @voidzero-dev/vite-plus-test/plugins/browser-playwright -@vitest/browser-webdriverio -> @voidzero-dev/vite-plus-test/plugins/browser-webdriverio -@vitest/browser-preview -> @voidzero-dev/vite-plus-test/plugins/browser-preview -``` - ---- - -## Ensuring Bundle Stability - -### Build-time Validation - -The build script includes `validateExternalDeps()` which: - -1. Scans all bundled JS files using `oxc-parser` -2. Extracts all external import specifiers -3. Verifies every external dependency is declared in `dependencies` or `peerDependencies` -4. Reports undeclared externals that would fail at runtime - -If this validation fails, the build will report which packages need to be added. - -### Testing Strategy - -| Test Type | What It Validates | -| --------------------------------------------------------------- | -------------------------------------------------- | -| **Snap tests** (`packages/cli/snap-tests/vitest-browser-mode/`) | Browser mode works after bundling | -| **Ecosystem CI** (`ecosystem-ci/`) | Real-world projects work with bundled vitest | -| **CI workflows** | Multi-platform validation (Ubuntu, Windows, macOS) | - -### Vitest Upgrade Checklist - -When upgrading the vitest version: - -1. **Update version** in `packages/test/package.json`: - - ```json - { - "devDependencies": { - "vitest-dev": "^NEW_VERSION", - "@vitest/runner": "NEW_VERSION", - "@vitest/utils": "NEW_VERSION" - // ... all @vitest/* packages - } - } - ``` - -2. **Run build**: - - ```bash - pnpm -C packages/test build - ``` - -3. **Check for new externals**: If `validateExternalDeps()` reports new undeclared dependencies: - - Add to `dependencies` if it should be installed at runtime - - Add to `EXTERNAL_BLOCKLIST` if it should remain external (native bindings, optional) - - If it's a new leaf dep, it will be automatically bundled - -4. **Run tests**: - - ```bash - pnpm test - ``` - -5. **Run ecosystem CI**: - ```bash - pnpm -C ecosystem-ci test - ``` - -### Common Upgrade Issues - -| Issue | Cause | Solution | -| ----------------------- | ------------------------------ | -------------------------------------------------- | -| New undeclared external | New vitest dependency | Add to `dependencies` or `EXTERNAL_BLOCKLIST` | -| Browser test crashes | Node.js code leaked to browser | Check import rewriting in `rewriteVitestImports()` | -| Missing export | New @vitest/\* subpath export | Add to `VITEST_PACKAGE_TO_PATH` | -| pnpm override fails | New plugin export needed | Add to `createPluginExports()` | - ---- - -## Technical Reference - -### Build Flow - -``` -1. bundleVitest() Copy vitest-dev dist/ -> dist/ -2. copyVitestPackages() Copy @vitest/* -> dist/@vitest/ -3. convertTabsToSpaces() Normalize formatting for patches -4. collectLeafDependencies() Parse imports with oxc-parser -5. bundleLeafDeps() Bundle chai, pathe, etc -> dist/vendor/ -6. rewriteVitestImports() Rewrite @vitest/*, vitest/*, vite -7. patchVitestPkgRootPaths() Fix distRoot for relocated files -8. patchVitestBrowserPackage() Inject vendor-aliases plugin -9. patchBrowserProviderLocators() Fix browser-safe imports -10. Post-processing: - - patchVendorPaths() - - createBrowserCompatShim() - - createModuleRunnerStub() Browser-safe stub - - createNodeEntry() index-node.js with browser-provider - - copyBrowserClientFiles() - - createBrowserEntryFiles() browser/ entry files at package root - - patchModuleAugmentations() Rewrite @vitest/expect, @vitest/runner augmentations - - patchChaiTypeReference() Add @types/chai triple-slash reference - - createPluginExports() dist/plugins/* for pnpm overrides - - mergePackageJson() - - validateExternalDeps() -``` - -### Output Structure - -``` -browser/ # Entry files for ./browser export -├── context.js # Runtime guard (throws if not in browser) -└── context.d.ts # Re-exports from dist/@vitest/browser/context.d.ts -dist/ -├── @vitest/ # Copied packages (browser/Node.js safe) -│ ├── runner/ -│ ├── utils/ -│ ├── spy/ -│ ├── expect/ -│ ├── snapshot/ -│ ├── mocker/ -│ ├── pretty-format/ -│ ├── browser/ -│ └── browser-playwright/ -├── vendor/ # Bundled leaf dependencies -│ ├── chai.mjs -│ ├── pathe.mjs -│ ├── tinyrainbow.mjs -│ ├── magic-string.mjs -│ ├── estree-walker.mjs -│ ├── why-is-node-running.mjs -│ └── vitest_*.mjs # Browser stubs -├── plugins/ # Shims for pnpm overrides -│ ├── runner.mjs -│ ├── utils.mjs -│ └── ... (33+ files) -├── chunks/ # Vitest core chunks -├── client/ # Browser client files -├── index.js # Browser-safe entry -├── index-node.js # Node.js entry (includes browser-provider) -├── module-runner-stub.js # Browser-safe module-runner -└── browser-compat.js # @vitest/browser compatibility shim -``` - -### Browser/Node.js Separation - -The critical design decision is maintaining separation between browser and Node.js code: - -| Entry Point | Used By | Contains | -| -------------------- | --------------------- | --------------------------------- | -| `dist/index.js` | Browser tests | No Node.js-only code | -| `dist/index-node.js` | Node.js (config, CLI) | Includes browser-provider exports | - -This is achieved through: - -1. Conditional exports in package.json (`"node": "./dist/index-node.js"`) -2. Browser-safe stubs for `module-runner` -3. Import rewriting to prevent Node.js code from being pulled into browser bundles -4. `vendor-aliases` plugin injection to resolve imports at runtime: - - Handles `@vitest/*` imports → resolves to copied `dist/@vitest/` files - - Handles `vitest/*` subpaths → resolves to dist files (enables `vitest/browser-playwright` usage) - - Handles `vitest/browser-playwright`, `vitest/browser-webdriverio`, `vitest/browser-preview` → resolves to bundled browser providers - - Handles `@voidzero-dev/vite-plus-test/*` subpaths → maps to equivalent vitest paths - - Handles `vite-plus/test/*` subpaths → maps to equivalent vitest paths (CLI package) - - Intercepts `vitest/browser`, `@voidzero-dev/vite-plus-test/browser`, `vite-plus/test/browser` → returns virtual module ID for BrowserContext plugin - -### Key Constants - -```typescript -// Packages copied to dist/@vitest/ -const VITEST_PACKAGES_TO_COPY = [ - '@vitest/runner', - '@vitest/utils', - '@vitest/spy', - '@vitest/expect', - '@vitest/snapshot', - '@vitest/mocker', - '@vitest/pretty-format', - '@vitest/browser', - '@vitest/browser-playwright', - '@vitest/browser-webdriverio', - '@vitest/browser-preview', -]; - -// Packages that must NOT be bundled (from build.ts lines 131-158) -const EXTERNAL_BLOCKLIST = new Set([ - // Our own packages - resolved at runtime - '@voidzero-dev/vite-plus-core', - '@voidzero-dev/vite-plus-core/module-runner', - 'vite', - 'vitest', - - // Peer dependencies - consumers must provide these - '@edge-runtime/vm', - '@opentelemetry/api', - '@standard-schema/spec', // Types-only import from @vitest/expect - 'happy-dom', - 'jsdom', - - // Optional dependencies with bundling issues or native bindings - 'debug', // environment detection broken when bundled - 'playwright', // native bindings - 'webdriverio', // native bindings - - // Runtime deps (in package.json dependencies) - not bundled, resolved at install time - 'sirv', - 'ws', - 'pixelmatch', - 'pngjs', - - // MSW (Mock Service Worker) - optional peer dep of @vitest/mocker - 'msw', - 'msw/browser', - 'msw/core/http', -]); -``` diff --git a/packages/test/__tests__/build-artifacts.spec.ts b/packages/test/__tests__/build-artifacts.spec.ts deleted file mode 100644 index 641b98260c..0000000000 --- a/packages/test/__tests__/build-artifacts.spec.ts +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Verify that the @voidzero-dev/vite-plus-test build output (dist/) - * contains the expected files and that patches applied during the build - * (in build.ts) produce correct artifacts. - * - * These tests run against the already-built dist/ directory, ensuring - * that re-packaging patches produce correct artifacts. - */ -import fs from 'node:fs'; -import path from 'node:path'; -import url from 'node:url'; - -import { describe, expect, it } from 'vitest'; - -const testPkgDir = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '..'); -const distDir = path.join(testPkgDir, 'dist'); - -function findCliApiChunk(): string { - const chunksDir = path.join(distDir, 'chunks'); - const files = fs.readdirSync(chunksDir); - const chunk = files.find((f) => f.startsWith('cli-api.') && f.endsWith('.js')); - if (!chunk) { - throw new Error('cli-api chunk not found in dist/chunks/'); - } - return path.join(chunksDir, chunk); -} - -describe('build artifacts', () => { - describe('@vitest/browser/context.js', () => { - const contextPath = path.join(distDir, '@vitest/browser/context.js'); - - it('should exist', () => { - expect(fs.existsSync(contextPath), `${contextPath} should exist`).toBe(true); - }); - - it('should export page, cdp, and utils', () => { - const content = fs.readFileSync(contextPath, 'utf-8'); - expect(content).toMatch(/export\s*\{[^}]*page[^}]*\}/); - expect(content).toMatch(/export\s*\{[^}]*cdp[^}]*\}/); - expect(content).toMatch(/export\s*\{[^}]*utils[^}]*\}/); - }); - }); - - /** - * The vitest:vendor-aliases plugin must NOT resolve @vitest/browser/context - * to the static file. If it does, the BrowserContext plugin's virtual module - * (which provides the `server` export) is bypassed. - * - * See: https://github.com/voidzero-dev/vite-plus/issues/1086 - */ - describe('vitest:vendor-aliases plugin (regression test for #1086)', () => { - const browserIndexPath = path.join(distDir, '@vitest/browser/index.js'); - - it('should not map @vitest/browser/context in vendorMap', () => { - const content = fs.readFileSync(browserIndexPath, 'utf-8'); - // The vendorMap inside vitest:vendor-aliases should NOT contain - // '@vitest/browser/context' — it must be left for BrowserContext - // plugin to resolve as a virtual module. - const vendorAliasesMatch = content.match( - /name:\s*['"]vitest:vendor-aliases['"][\s\S]*?const vendorMap\s*=\s*\{([\s\S]*?)\}/, - ); - expect(vendorAliasesMatch, 'vitest:vendor-aliases plugin should exist').toBeTruthy(); - const vendorMapContent = vendorAliasesMatch![1]; - expect(vendorMapContent).not.toContain("'@vitest/browser/context'"); - }); - }); - - /** - * `convertTabsToSpaces()` in build.ts must not touch tabs inside string - * literals. Upstream `@vitest/snapshot` decides multi-line snapshot - * indentation via `indent.includes("\t")` — where `"\t"` is a literal - * tab byte in the bundled source. A blanket tab→spaces rewrite turned - * this into `indent.includes(" ")`, so every 2-space indent matched - * and the tab-appending branch always ran, producing tab-indented - * snapshots in 2-space files. - * - * See: https://github.com/voidzero-dev/vite-plus/issues/1553 - */ - describe('snapshot indent check (regression test for #1553)', () => { - const snapshotIndexPath = path.join(distDir, '@vitest/snapshot/index.js'); - - it('preserves the literal tab byte inside the indent.includes string', () => { - const content = fs.readFileSync(snapshotIndexPath, 'utf-8'); - expect(content).toContain('indent.includes("\t")'); - expect(content).not.toMatch(/indent\.includes\(" "\)/); - }); - }); - - /** - * Third-party packages that call `expect.extend()` internally - * (e.g., @testing-library/jest-dom) break under npm override because - * the vitest module instance is split, causing matchers to be registered - * on a different `chai` instance than the test runner uses. - * - * The build patches vitest's ModuleRunnerTransform plugin to auto-add - * these packages to `server.deps.inline`, so they are processed through - * Vite's transform pipeline and share the same module instance. - * - * See: https://github.com/voidzero-dev/vite-plus/issues/897 - */ - describe('server.deps.inline auto-inline (regression test for #897)', () => { - it('should contain the expected auto-inline packages', () => { - const content = fs.readFileSync(findCliApiChunk(), 'utf-8'); - expect(content).toContain('Auto-inline packages'); - expect(content).toContain('"@testing-library/jest-dom"'); - expect(content).toContain('"@storybook/test"'); - expect(content).toContain('"jest-extended"'); - }); - - it('should not override user inline config when set to true', () => { - const content = fs.readFileSync(findCliApiChunk(), 'utf-8'); - expect(content).toContain('server.deps.inline !== true'); - }); - }); -}); diff --git a/packages/test/build.ts b/packages/test/build.ts deleted file mode 100644 index dd313749cf..0000000000 --- a/packages/test/build.ts +++ /dev/null @@ -1,2649 +0,0 @@ -// Build Script for @voidzero-dev/vite-plus-test -// -// Bundles vitest and @vitest/* dependencies with browser/Node.js separation. -// -// ┌─────────────────────────────────────────────────────────────────────┐ -// │ BUILD FLOW │ -// ├─────────────────────────────────────────────────────────────────────┤ -// │ 1. bundleVitest() Copy vitest-dev → dist/ │ -// │ 2. copyVitestPackages() Copy @vitest/* → dist/@vitest/ │ -// │ 3. collectLeafDependencies() Parse imports with oxc-parser │ -// │ 4. bundleLeafDeps() Bundle chai, pathe, etc → dist/vendor/ │ -// │ 5. rewriteVitestImports() Rewrite @vitest/*, vitest/*, vite │ -// │ 6. patchVitestPkgRootPaths() Fix distRoot for relocated files │ -// │ 7. patchVitestBrowserPackage() Inject vendor-aliases plugin │ -// │ 8. patchBrowserProviderLocators() Fix browser-safe imports │ -// │ 9. Post-processing: │ -// │ - patchVendorPaths() │ -// │ - createBrowserCompatShim() │ -// │ - createModuleRunnerStub() Browser-safe stub │ -// │ - createNodeEntry() index-node.js with browser-provider│ -// │ - copyBrowserClientFiles() │ -// │ - createPluginExports() dist/plugins/* for pnpm overrides │ -// │ - mergePackageJson() │ -// │ - validateExternalDeps() │ -// └─────────────────────────────────────────────────────────────────────┘ -// -// Output Structure: -// dist/@vitest/* - Copied packages (browser/Node.js safe) -// dist/vendor/* - Bundled leaf dependencies -// dist/plugins/* - Shims for pnpm overrides -// dist/index.js - Browser-safe entry -// dist/index-node.js - Node.js entry (includes browser-provider) -// -// Key Design: -// - COPY @vitest/* to preserve browser/Node.js separation -// - BUNDLE only leaf deps (chai, etc.) to reduce install size -// - Separate entries prevent __vite__injectQuery errors in browser - -import { existsSync } from 'node:fs'; -import { - copyFile, - glob as fsGlob, - mkdir, - readFile, - readdir, - rm, - stat, - writeFile, -} from 'node:fs/promises'; -import { builtinModules } from 'node:module'; -import { basename, join, parse, resolve, dirname, relative } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -import { parseSync } from 'oxc-parser'; -import { format } from 'oxfmt'; -import { build } from 'rolldown'; -import { dts } from 'rolldown-plugin-dts'; - -import { generateLicenseFile } from '../../scripts/generate-license.js'; -import pkg from './package.json' with { type: 'json' }; - -const projectDir = dirname(fileURLToPath(import.meta.url)); -const vitestSourceDir = resolve(projectDir, 'node_modules/vitest-dev'); -const distDir = resolve(projectDir, 'dist'); -const vendorDir = resolve(distDir, 'vendor'); - -const CORE_PACKAGE_NAME = '@voidzero-dev/vite-plus-core'; -const TEST_PACKAGE_NAME = '@voidzero-dev/vite-plus-test'; - -// @vitest/* packages to copy (not bundle) to preserve browser/Node.js separation -// These are copied from node_modules to dist/@vitest/ to avoid shared chunks -// that mix Node.js-only code with browser code -const VITEST_PACKAGES_TO_COPY = [ - '@vitest/runner', - '@vitest/utils', - '@vitest/spy', - '@vitest/expect', - '@vitest/snapshot', - '@vitest/mocker', - '@vitest/pretty-format', - '@vitest/browser', - '@vitest/browser-playwright', - '@vitest/browser-webdriverio', - '@vitest/browser-preview', -] as const; - -// Mapping from @vitest/* package specifiers to their paths within dist/@vitest/ -// Used for import rewriting and vendor-aliases plugin -const VITEST_PACKAGE_TO_PATH: Record = { - // @vitest/runner - '@vitest/runner': '@vitest/runner/index.js', - '@vitest/runner/utils': '@vitest/runner/utils.js', - '@vitest/runner/types': '@vitest/runner/types.js', - // @vitest/utils - '@vitest/utils': '@vitest/utils/index.js', - '@vitest/utils/source-map': '@vitest/utils/source-map.js', - '@vitest/utils/source-map/node': '@vitest/utils/source-map/node.js', - '@vitest/utils/error': '@vitest/utils/error.js', - '@vitest/utils/helpers': '@vitest/utils/helpers.js', - '@vitest/utils/display': '@vitest/utils/display.js', - '@vitest/utils/timers': '@vitest/utils/timers.js', - '@vitest/utils/highlight': '@vitest/utils/highlight.js', - '@vitest/utils/offset': '@vitest/utils/offset.js', - '@vitest/utils/resolver': '@vitest/utils/resolver.js', - '@vitest/utils/serialize': '@vitest/utils/serialize.js', - '@vitest/utils/constants': '@vitest/utils/constants.js', - '@vitest/utils/diff': '@vitest/utils/diff.js', - // @vitest/spy - '@vitest/spy': '@vitest/spy/index.js', - // @vitest/expect - '@vitest/expect': '@vitest/expect/index.js', - // @vitest/snapshot - '@vitest/snapshot': '@vitest/snapshot/index.js', - '@vitest/snapshot/environment': '@vitest/snapshot/environment.js', - '@vitest/snapshot/manager': '@vitest/snapshot/manager.js', - // @vitest/mocker - '@vitest/mocker': '@vitest/mocker/index.js', - '@vitest/mocker/node': '@vitest/mocker/node.js', - '@vitest/mocker/browser': '@vitest/mocker/browser.js', - '@vitest/mocker/redirect': '@vitest/mocker/redirect.js', - '@vitest/mocker/transforms': '@vitest/mocker/transforms.js', - '@vitest/mocker/automock': '@vitest/mocker/automock.js', - '@vitest/mocker/register': '@vitest/mocker/register.js', - // @vitest/pretty-format - '@vitest/pretty-format': '@vitest/pretty-format/index.js', - // @vitest/browser - '@vitest/browser': '@vitest/browser/index.js', - '@vitest/browser/context': '@vitest/browser/context.js', - '@vitest/browser/client': '@vitest/browser/client.js', - '@vitest/browser/locators': '@vitest/browser/locators.js', - // @vitest/browser-playwright - '@vitest/browser-playwright': '@vitest/browser-playwright/index.js', - // @vitest/browser-webdriverio - '@vitest/browser-webdriverio': '@vitest/browser-webdriverio/index.js', - // @vitest/browser-preview - '@vitest/browser-preview': '@vitest/browser-preview/index.js', -}; - -// Packages that should NOT be bundled into dist/vendor/ (remain external at runtime) -// There are two categories: -// 1. Runtime deps (also in package.json dependencies) - installed with the package, not bundled -// 2. Peer/optional deps (also in peerDependencies) - users must install themselves -const EXTERNAL_BLOCKLIST = new Set([ - // Our own packages - resolved at runtime - CORE_PACKAGE_NAME, - `${CORE_PACKAGE_NAME}/module-runner`, - 'vite', - 'vitest', - - // Peer dependencies - consumers must provide these - '@edge-runtime/vm', - '@opentelemetry/api', - '@standard-schema/spec', // Types-only import from @vitest/expect - 'happy-dom', - 'jsdom', - - // Optional dependencies with bundling issues or native bindings - 'debug', // environment detection broken when bundled - 'playwright', // native bindings - 'webdriverio', // native bindings - - // Runtime deps (in package.json dependencies) - not bundled, resolved at install time - 'sirv', - 'ws', - 'pixelmatch', - 'pngjs', - - // MSW (Mock Service Worker) - optional peer dep of @vitest/mocker - 'msw', - 'msw/browser', - 'msw/core/http', -]); - -// CJS packages that need their default export destructured to named exports -const CJS_REEXPORT_PACKAGES = new Set(['expect-type']); - -// Node built-in modules (including node: prefix variants) -const NODE_BUILTINS = new Set([...builtinModules, ...builtinModules.map((m) => `node:${m}`)]); - -// Step 1: Copy vitest-dev dist files (rewriting vite -> core package) -await bundleVitest(); - -// Step 1.5: Rebrand vitest CLI output as "vp test" with vite-plus version -await brandVitest(); - -// Step 2: Copy @vitest/* packages from node_modules to dist/@vitest/ -// This preserves the original file structure to maintain browser/Node.js separation -await copyVitestPackages(); - -// Step 2.5: Convert tabs to spaces in all copied JS files for consistent formatting -await convertTabsToSpaces(); - -// Step 3: Collect leaf dependencies from copied @vitest/* files -// These are external packages like tinyrainbow, pathe, chai, etc. -const leafDeps = await collectLeafDependencies(); - -// Step 4: Bundle only leaf dependencies into dist/vendor/ -// Unlike bundling @vitest/* directly, this avoids shared chunks that mix browser/Node.js code -const leafDepToVendorPath = await bundleLeafDeps(leafDeps); - -// Step 5: Rewrite imports in copied @vitest/* and vitest-dev files -// - @vitest/* -> relative paths to dist/@vitest/ -// - leaf deps -> relative paths to dist/vendor/ -// - vite -> @voidzero-dev/vite-plus-core -await rewriteVitestImports(leafDepToVendorPath); - -// Step 6: Fix pkgRoot resolution in all @vitest/* packages -// Files are now at dist/@vitest/*/index.js, so "../.." needs to become "../../.." -await patchVitestPkgRootPaths(); - -// Step 7: Patch @vitest/browser package (vendor-aliases plugin, exclude list) -await patchVitestBrowserPackage(); - -// Step 8: Patch browser provider locators.js files for browser-safe imports -await patchBrowserProviderLocators(); - -// Step 9: Post-processing -await patchVendorPaths(); -await patchVitestCoreResolver(); -await createBrowserCompatShim(); -await createModuleRunnerStub(); -await createNodeEntry(); -await copyBrowserClientFiles(); -await createBrowserEntryFiles(); -await patchModuleAugmentations(); -await patchChaiTypeReference(); -await patchMockerHoistedModule(); -await patchServerDepsInline(); -const pluginExports = await createPluginExports(); -await mergePackageJson(pluginExports); -generateLicenseFile({ - title: 'Vite-Plus test license', - packageName: 'Vite-Plus', - outputPath: join(projectDir, 'LICENSE'), - coreLicensePath: join(projectDir, '..', '..', 'LICENSE'), - bundledPaths: [distDir], - resolveFrom: [projectDir, join(projectDir, '..', '..')], - extraPackages: [ - { packageDir: vitestSourceDir }, - ...VITEST_PACKAGES_TO_COPY.map((packageName) => ({ - packageDir: resolve(projectDir, 'node_modules', packageName), - })), - ], -}); -if (!existsSync(join(projectDir, 'LICENSE'))) { - throw new Error('LICENSE was not generated during build'); -} -await validateExternalDeps(); - -async function mergePackageJson(pluginExports: Array<{ exportPath: string; shimFile: string }>) { - const vitestPackageJsonPath = join(vitestSourceDir, 'package.json'); - const destPackageJsonPath = resolve(projectDir, 'package.json'); - - const vitestPkg = JSON.parse(await readFile(vitestPackageJsonPath, 'utf-8')); - const destPkg = JSON.parse(await readFile(destPackageJsonPath, 'utf-8')); - - // Fields to merge from vitest-dev package.json (excluding dependencies since we bundle them) - const fieldsToMerge = [ - 'imports', - 'exports', - 'main', - 'module', - 'types', - 'engines', - 'peerDependencies', - 'peerDependenciesMeta', - ] as const; - - for (const field of fieldsToMerge) { - if (vitestPkg[field] !== undefined) { - destPkg[field] = vitestPkg[field]; - } - } - - // Remove bundled @vitest/* packages from peerDependencies - // These browser provider packages are now bundled, so users don't need to install them - const bundledPeerDeps = [ - '@vitest/browser-playwright', - '@vitest/browser-webdriverio', - '@vitest/browser-preview', - ]; - if (destPkg.peerDependencies) { - for (const dep of bundledPeerDeps) { - delete destPkg.peerDependencies[dep]; - } - } - if (destPkg.peerDependenciesMeta) { - for (const dep of bundledPeerDeps) { - delete destPkg.peerDependenciesMeta[dep]; - } - } - - destPkg.bundledVersions = { - ...destPkg.bundledVersions, - vitest: vitestPkg.version, - }; - - // Add @vitest/browser compatible export (for when this package overrides @vitest/browser) - // The main "." export is what's used when code imports from @vitest/browser - if (destPkg.exports) { - // Add conditional Node.js export to the main entry - // Node.js code (like @vitest/browser-playwright) uses index-node.js which includes - // browser-provider exports. Browser code uses index.js which is safe. - // This separation prevents Node.js-only code (like __vite__injectQuery) from being - // loaded in the browser, which would cause "Identifier already declared" errors. - // - // IMPORTANT: The 'browser' condition must come BEFORE 'node' because vitest passes - // custom --conditions (like 'browser') to worker processes when frameworks like Nuxt - // set edge/cloudflare presets. Without the 'browser' condition here, Node.js would - // match 'node' first, loading index-node.js which imports @vitest/browser/index.js, - // which imports 'ws'. With --conditions browser active, 'ws' resolves to its browser - // stub (ws/browser.js) that doesn't export WebSocketServer, causing a SyntaxError. - // See: https://github.com/voidzero-dev/vite-plus/issues/831 - if (destPkg.exports['.'] && destPkg.exports['.'].import) { - destPkg.exports['.'].import = { - types: destPkg.exports['.'].import.types, - browser: destPkg.exports['.'].import.default, - node: './dist/index-node.js', - default: destPkg.exports['.'].import.default, - }; - } - - destPkg.exports['./browser-compat'] = { - default: './dist/browser-compat.js', - }; - - // Add @vitest/browser-compatible subpath exports - // These are needed when this package is used as a pnpm override for @vitest/browser - // Files are copied to dist/ (not dist/vendor/) to match path resolution in bundled code - destPkg.exports['./client'] = { - default: './dist/client.js', - }; - // Point to @vitest/browser/context.js so that tests and init scripts share the same module - // This is critical: the init script (locators.js) calls page.extend() on this module, - // and tests must use the SAME module instance to see the extended methods - destPkg.exports['./context'] = { - types: './browser/context.d.ts', - default: './dist/@vitest/browser/context.js', - }; - // Also export ./browser/context for users importing vite-plus/test/browser/context - destPkg.exports['./browser/context'] = { - types: './browser/context.d.ts', - default: './dist/@vitest/browser/context.js', - }; - destPkg.exports['./locators'] = { - default: './dist/locators.js', - }; - destPkg.exports['./matchers'] = { - default: './dist/dummy.js', // Placeholder - }; - destPkg.exports['./utils'] = { - default: './dist/dummy.js', // Placeholder - }; - - // Add @vitest/browser-playwright compatible export - // Users can import { playwright } from 'vitest/browser-playwright' - destPkg.exports['./browser-playwright'] = { - types: './dist/@vitest/browser-playwright/index.d.ts', - default: './dist/@vitest/browser-playwright/index.js', - }; - - // Add @vitest/browser-webdriverio compatible export - // Users can import { webdriverio } from 'vitest/browser-webdriverio' - destPkg.exports['./browser-webdriverio'] = { - types: './dist/@vitest/browser-webdriverio/index.d.ts', - default: './dist/@vitest/browser-webdriverio/index.js', - }; - - // Add @vitest/browser-preview compatible export - // Users can import { preview } from 'vitest/browser-preview' - destPkg.exports['./browser-preview'] = { - types: './dist/@vitest/browser-preview/index.d.ts', - default: './dist/@vitest/browser-preview/index.js', - }; - - // Add browser/providers/* alias exports for compatibility - // Some vitest examples use the nested path format - destPkg.exports['./browser/providers/playwright'] = { - types: './dist/@vitest/browser-playwright/index.d.ts', - default: './dist/@vitest/browser-playwright/index.js', - }; - destPkg.exports['./browser/providers/webdriverio'] = { - types: './dist/@vitest/browser-webdriverio/index.d.ts', - default: './dist/@vitest/browser-webdriverio/index.js', - }; - destPkg.exports['./browser/providers/preview'] = { - types: './dist/@vitest/browser-preview/index.d.ts', - default: './dist/@vitest/browser-preview/index.js', - }; - - // Add plugin exports for all bundled @vitest/* packages - // This allows pnpm overrides to redirect: @vitest/runner -> vitest/plugins/runner - for (const { exportPath, shimFile } of pluginExports) { - destPkg.exports[exportPath] = { - default: shimFile, - }; - } - } - - // Merge vitest dependencies into devDependencies (since we bundle them) - // Skip packages that are already in dependencies (runtime deps) - if (vitestPkg.dependencies) { - destPkg.devDependencies = destPkg.devDependencies || {}; - for (const [dep, version] of Object.entries(vitestPkg.dependencies)) { - // Skip vite - we use our own core package - if (dep === 'vite') { - continue; - } - // Skip packages already in dependencies (they're runtime deps, not dev-only) - if (destPkg.dependencies && destPkg.dependencies[dep]) { - continue; - } - // Don't override existing devDependencies - if (!destPkg.devDependencies[dep]) { - destPkg.devDependencies[dep] = version; - } - } - } - - const { code, errors } = await format( - destPackageJsonPath, - JSON.stringify(destPkg, null, 2) + '\n', - { - experimentalSortPackageJson: true, - }, - ); - if (errors.length > 0) { - for (const error of errors) { - console.error(error); - } - process.exit(1); - } - await writeFile(destPackageJsonPath, code); -} - -async function bundleVitest() { - const vitestDestDir = projectDir; - - await mkdir(vitestDestDir, { recursive: true }); - - // Get all vitest files excluding node_modules and package.json - const vitestFiles = fsGlob(join(vitestSourceDir, '**/*'), { - exclude: [ - join(vitestSourceDir, 'node_modules/**'), - join(vitestSourceDir, 'package.json'), - join(vitestSourceDir, 'README.md'), - join(vitestSourceDir, 'LICENSE.md'), - ], - }); - - for await (const file of vitestFiles) { - const stats = await stat(file); - if (!stats.isFile()) { - continue; - } - - const relativePath = file.replace(vitestSourceDir, ''); - const destPath = join(vitestDestDir, relativePath); - - await mkdir(parse(destPath).dir, { recursive: true }); - - // Rewrite vite imports in .js, .mjs, and .cjs files - if ( - file.endsWith('.js') || - file.endsWith('.mjs') || - file.endsWith('.cjs') || - file.endsWith('.d.ts') || - file.endsWith('.d.cts') - ) { - let content = await readFile(file, 'utf-8'); - content = content - .replaceAll(/from ['"]vite['"]/g, `from '${CORE_PACKAGE_NAME}'`) - .replaceAll(/import\(['"]vite['"]\)/g, `import('${CORE_PACKAGE_NAME}')`) - .replaceAll(/require\(['"]vite['"]\)/g, `require('${CORE_PACKAGE_NAME}')`) - .replaceAll(/require\("vite"\)/g, `require("${CORE_PACKAGE_NAME}")`) - .replaceAll(`import 'vite';`, `import '${CORE_PACKAGE_NAME}';`) - .replaceAll(`'vite/module-runner'`, `'${CORE_PACKAGE_NAME}/module-runner'`) - .replaceAll(`declare module "vite"`, `declare module "${CORE_PACKAGE_NAME}"`) - .replaceAll(/import\(['"]vitest['"]\)/g, `import('${TEST_PACKAGE_NAME}')`); - console.log(`Replaced vite imports in ${destPath}`); - await writeFile(destPath, content, 'utf-8'); - } else { - await copyFile(file, destPath); - } - } -} - -/** - * Rebrand vitest CLI output as "vp test" with Vite+ banner styling. - * Patches bundled chunks to replace vitest branding and align banner output. - */ -async function brandVitest() { - const chunksDir = resolve(projectDir, 'dist/chunks'); - const cacFiles: string[] = []; - for await (const file of fsGlob(join(chunksDir, 'cac.*.js'))) { - cacFiles.push(file); - } - if (cacFiles.length === 0) { - throw new Error('brandVitest: no cac chunk found in dist/chunks/'); - } - for (const cacFile of cacFiles) { - let content = await readFile(cacFile, 'utf-8'); - - function patchString(label: string, search: string | RegExp, replacement: string) { - const before = content; - content = - typeof search === 'string' - ? content.replace(search, replacement) - : content.replace(search, replacement); - if (content === before) { - throw new Error( - `brandVitest: failed to patch "${label}" — pattern not found in ${cacFile}`, - ); - } - } - - // 1. CLI name: cac("vitest") → cac("vp test") - patchString('cac name', 'cac("vitest")', 'cac("vp test")'); - - // 2. Version: var version = "" → use VP_VERSION env var with fallback - patchString( - 'version', - /var version = "(\d+\.\d+\.\d+[^"]*)"/, - 'var version = process.env.VP_VERSION || "$1"', - ); - - // 3. Banner regex: /^vitest\/\d+\.\d+\.\d+$/ → /^vp test\/[\d.]+$/ - patchString('banner regex', '/^vitest\\/\\d+\\.\\d+\\.\\d+$/', '/^vp test\\/[\\d.]+$/'); - - // 4. Help text: $ vitest --help → $ vp test --help - patchString('help text', '$ vitest --help --expand-help', '$ vp test --help --expand-help'); - - await writeFile(cacFile, content, 'utf-8'); - console.log(`Branded vitest → vp test in ${cacFile}`); - } - - const cliApiFiles: string[] = []; - for await (const file of fsGlob(join(chunksDir, 'cli-api.*.js'))) { - cliApiFiles.push(file); - } - if (cliApiFiles.length === 0) { - throw new Error('brandVitest: no cli-api chunk found in dist/chunks/'); - } - - for (const cliApiFile of cliApiFiles) { - let content = await readFile(cliApiFile, 'utf-8'); - - function patchString(label: string, search: string | RegExp, replacement: string) { - const before = content; - content = - typeof search === 'string' - ? content.replace(search, replacement) - : content.replace(search, replacement); - if (content === before) { - throw new Error( - `brandVitest: failed to patch "${label}" — pattern not found in ${cliApiFile}`, - ); - } - } - - // Remove one extra leading newline before DEV/RUN banner. - patchString( - 'banner leading newline', - /printBanner\(\) \{\n\t\tthis\.log\(\);\n/, - 'printBanner() {\n', - ); - - // Use a blue badge for both DEV and RUN. - patchString( - 'banner color', - /const color = this\.ctx\.config\.watch \? "blue" : "[a-z]+";\n\t\tconst mode = this\.ctx\.config\.watch \? "DEV" : "RUN";/, - 'const mode = this.ctx.config.watch ? "DEV" : "RUN";\n\t\tconst label = c.bold(c.inverse(c.blue(` ${mode} `)));', - ); - - // Remove the version from the banner line and render a high-contrast label. - patchString( - 'banner version text', - /this\.log\(withLabel\(color, mode, (?:""|`v\$\{this\.ctx\.version\} `)\) \+ c\.gray\(this\.ctx\.config\.root\)\);/, - 'this.log(`${label} ${c.gray(this.ctx.config.root)}`);', - ); - - await writeFile(cliApiFile, content, 'utf-8'); - console.log(`Branded vitest banner in ${cliApiFile}`); - } -} - -/** - * Copy @vitest/* packages from node_modules to dist/@vitest/ - * This preserves the original file structure to maintain browser/Node.js separation. - * Unlike bundling with Rolldown, copying avoids creating shared chunks that mix - * Node.js-only code with browser code. - */ -async function copyVitestPackages() { - console.log('\nCopying @vitest/* packages to dist/@vitest/...'); - - const vitestDir = resolve(distDir, '@vitest'); - await rm(vitestDir, { recursive: true, force: true }); - await mkdir(vitestDir, { recursive: true }); - - let totalCopied = 0; - - for (const pkg of VITEST_PACKAGES_TO_COPY) { - const pkgName = pkg.replace('@vitest/', ''); - const srcDir = resolve(projectDir, `node_modules/${pkg}/dist`); - const destPkgDir = resolve(vitestDir, pkgName); - - try { - await stat(srcDir); - } catch { - console.log(` Warning: ${pkg} not installed, skipping`); - continue; - } - - console.log(` Copying ${pkg}...`); - const copied = await copyDirRecursive(srcDir, destPkgDir); - totalCopied += copied; - console.log(` -> ${copied} files`); - - // Copy root .d.ts files from @vitest/browser package directory. - // These are type definitions that live at the package root (not in dist/), - // e.g. context.d.ts, matchers.d.ts, aria-role.d.ts, utils.d.ts. - // Dynamically scan instead of hardcoding to handle future upstream additions. - if (pkg === '@vitest/browser') { - const pkgRoot = resolve(projectDir, `node_modules/${pkg}`); - try { - const pkgEntries = await readdir(pkgRoot); - for (const entry of pkgEntries) { - if (entry.endsWith('.d.ts')) { - await copyFile(join(pkgRoot, entry), join(destPkgDir, entry)); - console.log(` + copied ${entry}`); - totalCopied++; - } - } - } catch { - // Package root not readable, skip - } - } - } - - console.log(`\nCopied ${totalCopied} files to dist/@vitest/`); -} - -/** - * Recursively copy a directory - */ -async function copyDirRecursive(srcDir: string, destDir: string): Promise { - await mkdir(destDir, { recursive: true }); - const entries = await readdir(srcDir, { withFileTypes: true }); - let count = 0; - - for (const entry of entries) { - const srcPath = join(srcDir, entry.name); - const destPath = join(destDir, entry.name); - - if (entry.isDirectory()) { - count += await copyDirRecursive(srcPath, destPath); - } else if (entry.isFile()) { - await copyFile(srcPath, destPath); - count++; - } - } - - return count; -} - -/** - * Collect leaf dependencies from copied @vitest/* files AND vitest core dist files. - * These are external packages that should be bundled (tinyrainbow, pathe, chai, expect-type, etc.) - * but NOT @vitest/*, vitest/*, vite/*, node built-ins, or blocklisted packages. - */ -async function collectLeafDependencies(): Promise> { - console.log('\nCollecting leaf dependencies from dist/...'); - - const leafDeps = new Set(); - const vitestDir = resolve(distDir, '@vitest'); - - // Scan both @vitest/* packages AND vitest core dist files - const jsFiles = fsGlob([ - join(vitestDir, '**/*.js'), - join(distDir, '*.js'), - join(distDir, 'chunks/*.js'), - ]); - - for await (const file of jsFiles) { - const content = await readFile(file, 'utf-8'); - const result = parseSync(file, content, { sourceType: 'module' }); - - // Collect ESM static imports - for (const imp of result.module.staticImports) { - const specifier = imp.moduleRequest.value; - if (isLeafDependency(specifier)) { - leafDeps.add(specifier); - } - } - - // Collect ESM static exports (re-exports) - for (const exp of result.module.staticExports) { - for (const entry of exp.entries) { - if (entry.moduleRequest) { - const specifier = entry.moduleRequest.value; - if (isLeafDependency(specifier)) { - leafDeps.add(specifier); - } - } - } - } - - // Collect dynamic imports (only string literals) - for (const dynImp of result.module.dynamicImports) { - const rawText = content.slice(dynImp.moduleRequest.start, dynImp.moduleRequest.end); - if ( - (rawText.startsWith("'") && rawText.endsWith("'")) || - (rawText.startsWith('"') && rawText.endsWith('"')) - ) { - const specifier = rawText.slice(1, -1); - if (isLeafDependency(specifier)) { - leafDeps.add(specifier); - } - } - } - } - - console.log(`Found ${leafDeps.size} leaf dependencies:`); - for (const dep of leafDeps) { - console.log(` - ${dep}`); - } - - return leafDeps; -} - -/** - * Check if a specifier is a leaf dependency that should be bundled. - * Leaf deps are external packages that are NOT: - * - @vitest/* (we copy these) - * - vitest or vitest/* (we copy vitest-dev) - * - vite or vite/* (we use our core package) - * - Node.js built-ins - * - Blocklisted packages - * - Relative paths - */ -function isLeafDependency(specifier: string): boolean { - // Relative paths - if (specifier.startsWith('.') || specifier.startsWith('/')) { - return false; - } - // @vitest/* packages (we copy these) - if (specifier.startsWith('@vitest/')) { - return false; - } - // vitest or vitest/* (we copy vitest-dev) - if (specifier === 'vitest' || specifier.startsWith('vitest/')) { - return false; - } - // vite or vite/* (we use our core package) - if (specifier === 'vite' || specifier.startsWith('vite/')) { - return false; - } - // Node.js built-ins - if (NODE_BUILTINS.has(specifier)) { - return false; - } - // Blocklisted packages - if (EXTERNAL_BLOCKLIST.has(specifier)) { - return false; - } - // Node.js subpath imports (#module-evaluator, etc.) - if (specifier.startsWith('#')) { - return false; - } - // Invalid specifiers - if (!/^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*/.test(specifier)) { - return false; - } - return true; -} - -/** - * Bundle only leaf dependencies into dist/vendor/. - * Only bundles non-@vitest deps (tinyrainbow, pathe, chai, etc.) - * to avoid shared chunks that mix Node.js and browser code. - */ -async function bundleLeafDeps(leafDeps: Set): Promise> { - console.log('\nBundling leaf dependencies...'); - - await rm(vendorDir, { recursive: true, force: true }); - await mkdir(vendorDir, { recursive: true }); - - const specifierToVendorPath = new Map(); - - if (leafDeps.size === 0) { - console.log(' No leaf dependencies to bundle.'); - return specifierToVendorPath; - } - - // Build input object with all leaf deps - const input: Record = {}; - for (const dep of leafDeps) { - const safeName = safeFileName(dep); - input[safeName] = dep; - } - - try { - await build({ - input, - output: { - dir: vendorDir, - format: 'esm', - entryFileNames: '[name].mjs', - chunkFileNames: 'shared-[hash].mjs', - }, - platform: 'neutral', - treeshake: false, - external: [ - // Keep node built-ins external - ...NODE_BUILTINS, - // Keep blocklisted packages external - ...EXTERNAL_BLOCKLIST, - // Keep @vitest/* external (we copy them) - /@vitest\//, - // Keep vitest external (we copy it) - /^vitest(\/.*)?$/, - // Keep vite external (we use core package) - /^vite(\/.*)?$/, - ], - resolve: { - conditionNames: ['node', 'import', 'default'], - mainFields: ['module', 'main'], - }, - logLevel: 'warn', - }); - - const dtsInput = { ...input }; - - for (const name of Object.keys(dtsInput)) { - const vendorDtsPath = join(vendorDir, `vendor_${name}.d.ts`); - dtsInput[name] = vendorDtsPath; - await writeFile(vendorDtsPath, `export * from '${name}';`, 'utf-8'); - } - - await build({ - input: dtsInput, - output: { - dir: vendorDir, - format: 'esm', - entryFileNames: '[name].mts', - }, - plugins: [ - dts({ - dtsInput: true, - oxc: true, - resolver: 'oxc', - emitDtsOnly: true, - tsconfig: false, - }), - ], - }); - - for (const p of Object.values(dtsInput)) { - await rm(p); - } - - // Register all specifiers - for (const dep of leafDeps) { - const safeName = safeFileName(dep); - const vendorFilePath = join(vendorDir, `${safeName}.mjs`); - specifierToVendorPath.set(dep, vendorFilePath); - console.log(` -> vendor/${safeName}.mjs`); - - // Fix CJS packages that need named exports extracted from default - if (CJS_REEXPORT_PACKAGES.has(dep)) { - await fixCjsNamedExports(vendorFilePath, dep); - } - } - } catch (error) { - console.error('Failed to bundle leaf dependencies:', error); - throw error; - } - - console.log(`\nBundled ${specifierToVendorPath.size} leaf dependencies.`); - return specifierToVendorPath; -} - -/** - * Rewrite imports in all copied @vitest/* files and vitest-dev dist files. - * This handles: - * - @vitest/* -> relative paths to dist/@vitest/ - * - vitest/* -> relative paths to dist/ - * - vite -> @voidzero-dev/vite-plus-core - * - leaf deps -> relative paths to dist/vendor/ - */ -async function rewriteVitestImports(leafDepToVendorPath: Map) { - console.log('\nRewriting imports in @vitest/* and vitest core files...'); - - const vitestDir = resolve(distDir, '@vitest'); - let rewrittenCount = 0; - - // Scan both @vitest/* packages AND vitest core dist files - // Include .d.ts files so TypeScript type imports also get rewritten - const jsFiles = fsGlob([ - join(vitestDir, '**/*.js'), - join(vitestDir, '**/*.d.ts'), - join(distDir, '*.js'), - join(distDir, '*.d.ts'), - join(distDir, 'chunks/*.js'), - join(distDir, 'chunks/*.d.ts'), - ]); - - for await (const file of jsFiles) { - let content = await readFile(file, 'utf-8'); - const fileDir = dirname(file); - - // Build specifier map for this file - const specifierMap = new Map(); - - // Add @vitest/* mappings (relative paths) - for (const [pkg, destPath] of Object.entries(VITEST_PACKAGE_TO_PATH)) { - const absoluteDest = resolve(distDir, destPath); - let relativePath = relative(fileDir, absoluteDest); - relativePath = relativePath.split('\\').join('/'); // Windows fix - if (!relativePath.startsWith('.')) { - relativePath = './' + relativePath; - } - specifierMap.set(pkg, absoluteDest); - } - - // Add vitest/* mappings (relative to dist/) - const vitestSubpathRewrites: Record = { - vitest: resolve(distDir, 'index.js'), - 'vitest/node': resolve(distDir, 'node.js'), - 'vitest/config': resolve(distDir, 'config.js'), - // vitest/browser exports page, server, CDPSession, BrowserCommands, etc from @vitest/browser/context - // This matches vitest's own package.json exports: "./browser" -> "./browser/context.d.ts" - 'vitest/browser': resolve(distDir, '@vitest/browser/context.js'), - // vitest/internal/browser exports browser-safe __INTERNAL and stringify (NOT @vitest/browser/index.js which has Node.js code) - 'vitest/internal/browser': resolve(distDir, 'browser.js'), - 'vitest/runners': resolve(distDir, 'runners.js'), - 'vitest/suite': resolve(distDir, 'suite.js'), - 'vitest/environments': resolve(distDir, 'environments.js'), - 'vitest/coverage': resolve(distDir, 'coverage.js'), - 'vitest/reporters': resolve(distDir, 'reporters.js'), - 'vitest/snapshot': resolve(distDir, 'snapshot.js'), - 'vitest/mocker': resolve(distDir, 'mocker.js'), - }; - for (const [specifier, absolutePath] of Object.entries(vitestSubpathRewrites)) { - specifierMap.set(specifier, absolutePath); - } - - // Add leaf dep mappings (relative to vendor/) - for (const [specifier, vendorPath] of leafDepToVendorPath) { - specifierMap.set(specifier, vendorPath); - } - - // For files inside @vitest/browser/, preserve 'vitest/browser' as a bare specifier. - // These files run in browser context where the vitest:vendor-aliases plugin - // resolves 'vitest/browser' to the virtual module '\0vitest/browser', - // which provides browser-safe context API (page, server, userEvent, utils). - // Without this, 'vitest/browser' gets rewritten to './index.js' which resolves - // to the Node.js server file (~9000 lines of node:fs, ws, etc.) - if (file.includes('@vitest/browser') || file.includes('@vitest\\browser')) { - specifierMap.delete('vitest/browser'); - } - - // Rewrite using AST - const rewritten = rewriteImportsWithAst(content, file, false, specifierMap); - - // Also rewrite vite -> core package (simple string replacement since it's a package name) - let finalContent = rewritten - .replaceAll(/from ['"]vite['"]/g, `from '${CORE_PACKAGE_NAME}'`) - .replaceAll(/import\(['"]vite['"]\)/g, `import('${CORE_PACKAGE_NAME}')`) - .replaceAll(`'vite/module-runner'`, `'${CORE_PACKAGE_NAME}/module-runner'`); - - // Special handling for @vitest/mocker entry files that have redundant side-effect imports - // The original files have: import 'magic-string'; export {...} from './chunk-automock.js'; import 'estree-walker'; - // This is problematic because: - // 1. Side-effect imports are redundant (chunk files already import what they need) - // 2. Having imports after exports can confuse some module parsers - // Fix: Remove redundant side-effect imports from vendor deps in entry files - if (file.includes('@vitest/mocker') || file.includes('@vitest\\mocker')) { - // Get the base filename - const baseName = file.split(/[/\\]/).pop(); - // Only process entry files (not chunk files) - if (baseName && !baseName.startsWith('chunk-')) { - // Remove side-effect imports from vendor deps (these are redundant since chunk files import them) - finalContent = finalContent.replace(/import\s*['"][^'"]*vendor[^'"]*\.mjs['"];?\s*/g, ''); - } - } - - if (finalContent !== content) { - await writeFile(file, finalContent, 'utf-8'); - rewrittenCount++; - } - } - - console.log(` Rewrote imports in ${rewrittenCount} files`); - - // Also rewrite imports in the main vitest-dev dist files - console.log('\nRewriting imports in vitest-dev dist files...'); - let mainRewrittenCount = 0; - - const mainJsFiles = fsGlob(join(distDir, '*.js')); - const chunksJsFiles = fsGlob(join(distDir, 'chunks', '*.js')); - const workersJsFiles = fsGlob(join(distDir, 'workers', '*.js')); - - for await (const file of mainJsFiles) { - const rewritten = await rewriteDistFile(file, leafDepToVendorPath); - if (rewritten) { - mainRewrittenCount++; - } - } - for await (const file of chunksJsFiles) { - const rewritten = await rewriteDistFile(file, leafDepToVendorPath); - if (rewritten) { - mainRewrittenCount++; - } - } - for await (const file of workersJsFiles) { - const rewritten = await rewriteDistFile(file, leafDepToVendorPath); - if (rewritten) { - mainRewrittenCount++; - } - } - - console.log(` Rewrote imports in ${mainRewrittenCount} dist files`); -} - -/** - * Rewrite imports in a vitest-dev dist file. - * Returns true if the file was modified. - */ -async function rewriteDistFile( - file: string, - leafDepToVendorPath: Map, -): Promise { - let content = await readFile(file, 'utf-8'); - - // Build specifier map - const specifierMap = new Map(); - - // Add @vitest/* mappings - for (const [pkg, destPath] of Object.entries(VITEST_PACKAGE_TO_PATH)) { - const absoluteDest = resolve(distDir, destPath); - specifierMap.set(pkg, absoluteDest); - } - - // Add leaf dep mappings - for (const [specifier, vendorPath] of leafDepToVendorPath) { - specifierMap.set(specifier, vendorPath); - } - - // Add vitest/* subpath mappings - // NOTE: Do NOT include 'vitest/browser' - it must be handled by - // the vitest:browser:virtual-module:context plugin at runtime - const vitestSubpathRewrites: Record = { - vitest: resolve(distDir, 'index.js'), - 'vitest/node': resolve(distDir, 'node.js'), - 'vitest/config': resolve(distDir, 'config.js'), - // 'vitest/browser' - intentionally omitted, handled by virtual module plugin - 'vitest/internal/browser': resolve(distDir, 'browser.js'), - 'vitest/runners': resolve(distDir, 'runners.js'), - 'vitest/suite': resolve(distDir, 'suite.js'), - 'vitest/environments': resolve(distDir, 'environments.js'), - 'vitest/coverage': resolve(distDir, 'coverage.js'), - 'vitest/reporters': resolve(distDir, 'reporters.js'), - 'vitest/snapshot': resolve(distDir, 'snapshot.js'), - 'vitest/mocker': resolve(distDir, 'mocker.js'), - }; - for (const [specifier, absolutePath] of Object.entries(vitestSubpathRewrites)) { - specifierMap.set(specifier, absolutePath); - } - - // Add mappings for ./vendor/vitest_*.mjs relative imports - // These are vitest-dev's bundled @vitest/* packages that we've copied to dist/@vitest/ - const vendorToVitest: Record = { - './vendor/vitest_runner.mjs': resolve(distDir, '@vitest/runner/index.js'), - './vendor/vitest_runners.mjs': resolve(distDir, 'runners.js'), - './vendor/vitest_browser.mjs': resolve(distDir, '@vitest/browser/context.js'), - './vendor/vitest_internal_browser.mjs': resolve(distDir, 'browser.js'), - './vendor/vitest_utils.mjs': resolve(distDir, '@vitest/utils/index.js'), - './vendor/vitest_spy.mjs': resolve(distDir, '@vitest/spy/index.js'), - './vendor/vitest_snapshot.mjs': resolve(distDir, '@vitest/snapshot/index.js'), - './vendor/vitest_expect.mjs': resolve(distDir, '@vitest/expect/index.js'), - }; - for (const [vendorPath, destPath] of Object.entries(vendorToVitest)) { - specifierMap.set(vendorPath, destPath); - } - - let rewritten = rewriteImportsWithAst(content, file, false, specifierMap); - - // Strip module-runner side-effect import from index.js - // This import is Node.js-only and causes browser tests to hang when vitest/index.js - // is loaded in browser context (to get describe, it, expect, etc.) - // The module-runner contains Node.js code (process.platform, etc.) that browsers can't execute - if (basename(file) === 'index.js') { - rewritten = rewritten.replace( - /import\s*['"]@voidzero-dev\/vite-plus-core\/module-runner['"];?\s*/g, - '', - ); - } - - if (rewritten !== content) { - await writeFile(file, rewritten, 'utf-8'); - return true; - } - return false; -} - -/** - * Rewrite imports using oxc-parser AST for precise replacements - */ -function rewriteImportsWithAst( - content: string, - filePath: string, - isCjs: boolean, - specifierToVendorPath: Map, -): string { - // Use Map to deduplicate replacements by start position - const replacementMap = new Map(); - - // Helper to get relative path for a specifier - const getRelativePath = (specifier: string): string | null => { - const vendorPath = specifierToVendorPath.get(specifier); - if (!vendorPath) { - return null; - } - let relativePath = relative(dirname(filePath), vendorPath); - // Normalize to forward slashes for ES module imports (Windows uses backslashes) - relativePath = relativePath.split('\\').join('/'); - if (!relativePath.startsWith('.')) { - relativePath = './' + relativePath; - } - return relativePath; - }; - - // Helper to add replacement (deduplicates by start position) - const addReplacement = (start: number, end: number, newValue: string) => { - if (!replacementMap.has(start)) { - replacementMap.set(start, [start, end, newValue]); - } - }; - - // Parse with oxc-parser - const result = parseSync(filePath, content, { - sourceType: isCjs ? 'script' : 'module', - }); - - // Collect ESM static imports - for (const imp of result.module.staticImports) { - const specifier = imp.moduleRequest.value; - const relativePath = getRelativePath(specifier); - if (relativePath) { - // Replace the module request (including quotes) - addReplacement(imp.moduleRequest.start, imp.moduleRequest.end, `'${relativePath}'`); - } - } - - // Collect ESM static exports (re-exports) - for (const exp of result.module.staticExports) { - for (const entry of exp.entries) { - if (entry.moduleRequest) { - const specifier = entry.moduleRequest.value; - const relativePath = getRelativePath(specifier); - if (relativePath) { - addReplacement(entry.moduleRequest.start, entry.moduleRequest.end, `'${relativePath}'`); - } - } - } - } - - // Collect dynamic imports (only string literals) - for (const dynImp of result.module.dynamicImports) { - const rawText = content.slice(dynImp.moduleRequest.start, dynImp.moduleRequest.end); - if ( - (rawText.startsWith("'") && rawText.endsWith("'")) || - (rawText.startsWith('"') && rawText.endsWith('"')) - ) { - const specifier = rawText.slice(1, -1); - const relativePath = getRelativePath(specifier); - if (relativePath) { - addReplacement(dynImp.moduleRequest.start, dynImp.moduleRequest.end, `'${relativePath}'`); - } - } - } - - // For CJS files, also handle require() calls using regex (oxc-parser doesn't track these) - if (isCjs) { - const requireRegex = /require\s*\(\s*(['"])([^'"]+)\1\s*\)/g; - let match; - while ((match = requireRegex.exec(content)) !== null) { - const specifier = match[2]; - const relativePath = getRelativePath(specifier); - if (relativePath) { - // Calculate the position of just the string literal (including quotes) - const stringStart = match.index + match[0].indexOf(match[1]); - const stringEnd = stringStart + match[1].length + specifier.length + match[1].length; - addReplacement(stringStart, stringEnd, `'${relativePath}'`); - } - } - } - - // Sort replacements in reverse order (end to start) to preserve positions - // eslint-disable-next-line unicorn/no-array-sort -- safe: sorting a fresh spread copy - const replacements = [...replacementMap.values()].sort((a, b) => b[0] - a[0]); - - // Apply replacements - let result_content = content; - for (const [start, end, newValue] of replacements) { - result_content = result_content.slice(0, start) + newValue + result_content.slice(end); - } - - return result_content; -} - -/** - * Fix CJS packages that only export default - extract named exports from the default export - */ -async function fixCjsNamedExports(vendorFilePath: string, specifier: string) { - let content = await readFile(vendorFilePath, 'utf-8'); - - // Match pattern like: export default require_xxx(); - // and: export { }; - const defaultExportMatch = content.match(/export default (require_\w+)\(\);/); - - if (defaultExportMatch) { - const requireFn = defaultExportMatch[1]; - console.log(` Fixing CJS named exports for ${specifier}...`); - - const emptyExportMatch = content.match(/export \{\s*\};/); - if (emptyExportMatch) { - // Pattern: export default require_xxx();\nexport { }; - content = content.replace( - /export default (require_\w+)\(\);\s*\nexport \{\s*\};/, - `const __cjs_export__ = ${requireFn}();\nexport const { expectTypeOf } = __cjs_export__;\nexport default __cjs_export__;`, - ); - } else { - // Pattern: export default require_xxx(); (no empty export block) - content = content.replace( - /export default (require_\w+)\(\);/, - `const __cjs_export__ = ${requireFn}();\nexport const { expectTypeOf } = __cjs_export__;\nexport default __cjs_export__;`, - ); - } - - await writeFile(vendorFilePath, content, 'utf-8'); - } -} - -/** - * Create a safe filename from a specifier - */ -function safeFileName(specifier: string): string { - return specifier.replace(/[@/]/g, '_').replace(/^_/, ''); -} - -/** - * Patch pkgRoot/distRoot paths in vendor files. - * The bundled code assumes files are in dist/, but vendor files are in dist/vendor/ - * So "../.." needs to become "../../.." to correctly resolve to package root. - * Also patches relative file references like "context.js" to "../context.js". - */ -async function patchVendorPaths() { - console.log('\nPatching vendor paths...'); - - // Patterns that need one more level up due to vendor subdirectory - const pathPatterns = [ - // Package root calculation: "../.." -> "../../.." - { - original: `resolve$1(fileURLToPath(import.meta.url), "../..")`, - fixed: `resolve$1(fileURLToPath(import.meta.url), "../../..")`, - }, - // context.js reference: "context.js" -> "../context.js" - // This is used in browser server to resolve the vitest/browser/context export - { - original: `resolve$1(__dirname$1, "context.js")`, - fixed: `resolve$1(__dirname$1, "../context.js")`, - }, - ]; - - const vendorFiles = fsGlob(join(vendorDir, '*.mjs')); - let patchedCount = 0; - - for await (const file of vendorFiles) { - let content = await readFile(file, 'utf-8'); - let modified = false; - - for (const { original, fixed } of pathPatterns) { - if (content.includes(original)) { - content = content.replaceAll(original, fixed); - modified = true; - } - } - - if (modified) { - await writeFile(file, content, 'utf-8'); - console.log(` Patched paths in ${relative(distDir, file)}`); - patchedCount++; - } - } - - if (patchedCount === 0) { - console.log(' No vendor files needed path patching'); - } else { - console.log(` Successfully patched ${patchedCount} file(s)`); - } -} - -/** - * Patch VitestCoreResolver to resolve vite-plus/test directly. - * - * Problem: CLI's `export * from '@voidzero-dev/vite-plus-test'` creates a re-export - * chain that breaks module identity in Vite's SSR transform. expect.extend() - * mutations aren't visible through the re-export. - * - * Fix: Make VitestCoreResolver resolve both vite-plus/test and - * @voidzero-dev/vite-plus-test directly to dist/index.js, bypassing re-exports. - */ -async function patchVitestCoreResolver() { - console.log('\nPatching VitestCoreResolver for CLI package alias...'); - - let cliApiChunk: string | undefined; - for await (const chunk of fsGlob(join(distDir, 'chunks/cli-api.*.js'))) { - cliApiChunk = chunk; - break; - } - - if (!cliApiChunk) { - throw new Error('cli-api chunk not found'); - } - let content = await readFile(cliApiChunk, 'utf8'); - - // Find the VitestCoreResolver resolveId function and add our package aliases - const oldPattern = `async resolveId(id) { - if (id === "vitest") return resolve(distDir, "index.js"); - if (id.startsWith("@vitest/") || id.startsWith("vitest/"))`; - - const newCode = `async resolveId(id) { - if (id === "vitest") return resolve(distDir, "index.js"); - // Resolve CLI test path and test package directly to dist/index.js - // This bypasses the re-export chain and ensures module identity is preserved - if (id === "vite-plus/test" || id === "@voidzero-dev/vite-plus-test") { - return resolve(distDir, "index.js"); - } - // Handle subpaths: vite-plus/test/* -> vitest/* - if (id.startsWith("vite-plus/test/")) { - const subpath = id.slice("vite-plus/test/".length); - return this.resolve("vitest/" + subpath, join(ctx.config.root, "index.html"), { skipSelf: true }); - } - // Handle subpaths: @voidzero-dev/vite-plus-test/* -> vitest/* - if (id.startsWith("@voidzero-dev/vite-plus-test/")) { - const subpath = id.slice("@voidzero-dev/vite-plus-test/".length); - return this.resolve("vitest/" + subpath, join(ctx.config.root, "index.html"), { skipSelf: true }); - } - if (id.startsWith("@vitest/") || id.startsWith("vitest/"))`; - - if (!content.includes(oldPattern)) { - throw new Error( - 'Could not find VitestCoreResolver pattern to patch in ' + - cliApiChunk + - '. ' + - 'This likely means vitest code has changed and the patch needs to be updated.', - ); - } - - content = content.replace(oldPattern, newCode); - await writeFile(cliApiChunk, content); - console.log(' Patched VitestCoreResolver to resolve vite-plus/test directly'); -} - -/** - * Convert leading tabs to spaces in all JS files in dist/ for consistent - * formatting. This allows our patching code to use space-based patterns - * instead of tabs. - * - * Only leading whitespace is rewritten — tabs inside string or template - * literals are semantically meaningful (e.g. `indent.includes("\t")` in - * @vitest/snapshot picks the snapshot indent style by checking for a - * literal tab byte) and must be preserved. - * - * See: https://github.com/voidzero-dev/vite-plus/issues/1553 - */ -async function convertTabsToSpaces() { - console.log('\nConverting leading tabs to spaces in dist/...'); - - let convertedCount = 0; - - for await (const file of fsGlob(resolve(distDir, '**/*.js'))) { - const content = await readFile(file, 'utf-8'); - const converted = content.replace(/^\t+/gm, (match) => ' '.repeat(match.length)); - if (converted !== content) { - await writeFile(file, converted); - convertedCount++; - } - } - - console.log(` Converted ${convertedCount} files`); -} - -/** - * Fix pkgRoot path resolution in all `@vitest/*` packages. - * The original packages use resolve(import.meta.url, "../..") to find their package root. - * But our files are at `dist/@vitest/star/index.js`, so we need to go up 3 levels, not 2. - */ -async function patchVitestPkgRootPaths() { - console.log('\nFixing distRoot paths in @vitest/* packages...'); - - const vitestDir = resolve(distDir, '@vitest'); - let patchedCount = 0; - - for (const pkg of VITEST_PACKAGES_TO_COPY) { - const pkgName = pkg.replace('@vitest/', ''); - const indexPath = join(vitestDir, pkgName, 'index.js'); - - try { - await stat(indexPath); - } catch { - continue; - } - - let content = await readFile(indexPath, 'utf-8'); - - // The original @vitest/browser had index.js in the dist/ folder, so: - // pkgRoot = resolve(import.meta.url, "../..") -> @vitest/browser - // distRoot = resolve(pkgRoot, "dist") -> @vitest/browser/dist - // But our file is at dist/@vitest/browser/index.js, so distRoot should just be - // the directory containing index.js (not pkgRoot/dist) - // Replace both lines with just making distRoot = dirname of index.js - // Use regex to handle both top-level and indented occurrences - const oldPattern = - /( *)const pkgRoot = resolve\(fileURLToPath\(import\.meta\.url\), "\.\.\/\.\."\);\n\1const distRoot = resolve\(pkgRoot, "dist"\);/g; - const newContent = content.replace( - oldPattern, - '$1const distRoot = dirname(fileURLToPath(import.meta.url));', - ); - - if (newContent !== content) { - await writeFile(indexPath, newContent, 'utf-8'); - const matchCount = (content.match(oldPattern) || []).length; - console.log(` Fixed ${pkg}/index.js (${matchCount} occurrences)`); - patchedCount++; - } - } - - console.log(` Patched ${patchedCount} packages`); -} - -/** - * Patch the copied @vitest/browser package to: - * 1. Inject vitest:vendor-aliases plugin for @vitest/* resolution - * 2. Add native deps to the exclude list - * 3. Remove include patterns for bundled deps - */ -async function patchVitestBrowserPackage() { - console.log('\nPatching @vitest/browser package...'); - - const browserIndexPath = join(distDir, '@vitest/browser/index.js'); - - try { - await stat(browserIndexPath); - } catch { - console.log(' Warning: @vitest/browser not found in dist, skipping'); - return; - } - - let content = await readFile(browserIndexPath, 'utf-8'); - - // 1. Inject vitest:vendor-aliases plugin into BrowserPlugin return array - // This allows imports like @vitest/runner to be resolved to our copied @vitest files - // Exclude @vitest/browser/context from vendor-aliases so that BrowserContext - // plugin's resolveId can intercept the bare specifier and return the virtual - // module (which includes the dynamically generated `server` export). - // Without this, vendor-aliases resolves the bare specifier to the static - // context.js file (which has no `server`), bypassing BrowserContext entirely. - // See: https://github.com/voidzero-dev/vite-plus/issues/1086 - const VENDOR_ALIASES_EXCLUDE = new Set(['@vitest/browser/context']); - - const mappingEntries = Object.entries(VITEST_PACKAGE_TO_PATH) - .filter(([pkg]) => pkg.startsWith('@vitest/') && !VENDOR_ALIASES_EXCLUDE.has(pkg)) - .map(([pkg, file]) => `'${pkg}': resolve(packageRoot, '${file}')`) - .join(',\n '); - - // distRoot is @vitest/browser/ so we need to go up two levels to reach the actual dist root - const vendorAliasesPlugin = `{ - name: 'vitest:vendor-aliases', - enforce: 'pre', - resolveId(id) { - // distRoot is @vitest/browser/, packageRoot is the actual dist/ directory - const packageRoot = resolve(distRoot, '../..'); - // Resolve module-runner to a browser-safe stub - // This is critical: module-runner contains Node.js-only code (process.platform, etc.) - // that causes browsers to hang when loaded - if (id === '${CORE_PACKAGE_NAME}/module-runner' || id === 'vite/module-runner') { - return resolve(packageRoot, 'module-runner-stub.js'); - } - // Mark vite/core as external to prevent Node.js-only code from being bundled - // This prevents __vite__injectQuery duplication errors in browser tests - if (id === '${CORE_PACKAGE_NAME}' || id === 'vite') { - return { id, external: true }; - } - // Handle vitest/browser and package aliases - // Return virtual module ID so BrowserContext plugin can load it - // Supports: vitest/browser, @voidzero-dev/vite-plus-test/browser, vite-plus/test/browser - if (id === 'vitest/browser' || id === '@voidzero-dev/vite-plus-test/browser' || id === 'vite-plus/test/browser') { - return '\\0vitest/browser'; - } - // Handle vitest/* subpaths (resolve to our dist files) - // Also handle @voidzero-dev package aliases that resolve to the same files - const vitestSubpathMap = { - 'vitest': resolve(packageRoot, 'index.js'), - '@voidzero-dev/vite-plus-test': resolve(packageRoot, 'index.js'), - 'vite-plus/test': resolve(packageRoot, 'index.js'), - 'vitest/node': resolve(packageRoot, 'node.js'), - 'vitest/config': resolve(packageRoot, 'config.js'), - 'vitest/internal/browser': resolve(packageRoot, 'browser.js'), - 'vitest/runners': resolve(packageRoot, 'runners.js'), - 'vitest/suite': resolve(packageRoot, 'suite.js'), - 'vitest/environments': resolve(packageRoot, 'environments.js'), - 'vitest/coverage': resolve(packageRoot, 'coverage.js'), - 'vitest/reporters': resolve(packageRoot, 'reporters.js'), - 'vitest/snapshot': resolve(packageRoot, 'snapshot.js'), - 'vitest/mocker': resolve(packageRoot, 'mocker.js'), - // Browser providers - resolve to our bundled @vitest/browser-* packages - 'vitest/browser-playwright': resolve(packageRoot, '@vitest/browser-playwright/index.js'), - 'vitest/browser-webdriverio': resolve(packageRoot, '@vitest/browser-webdriverio/index.js'), - 'vitest/browser-preview': resolve(packageRoot, '@vitest/browser-preview/index.js'), - }; - if (vitestSubpathMap[id]) { - return vitestSubpathMap[id]; - } - // Handle @voidzero-dev/vite-plus-test/* subpaths (same as vitest/*) - if (id.startsWith('@voidzero-dev/vite-plus-test/')) { - const subpath = id.slice('@voidzero-dev/vite-plus-test/'.length); - const vitestEquiv = 'vitest/' + subpath; - if (vitestSubpathMap[vitestEquiv]) { - return vitestSubpathMap[vitestEquiv]; - } - } - // Handle vite-plus/test/* subpaths (CLI package paths, same as vitest/*) - if (id.startsWith('vite-plus/test/')) { - const subpath = id.slice('vite-plus/test/'.length); - const vitestEquiv = 'vitest/' + subpath; - if (vitestSubpathMap[vitestEquiv]) { - return vitestSubpathMap[vitestEquiv]; - } - } - // Handle @vitest/* packages (resolve to our copied files) - const vendorMap = { - ${mappingEntries} - }; - if (vendorMap[id]) { - return vendorMap[id]; - } - } - }`; - - // Find BrowserPlugin return array and inject plugin - const pluginArrayPattern = /(return \[)(\n +\{\n +enforce: "pre",\n +name: "vitest:browser",)/; - if (pluginArrayPattern.test(content)) { - content = content.replace(pluginArrayPattern, `$1\n ${vendorAliasesPlugin},$2`); - console.log(' Injected vitest:vendor-aliases plugin'); - } else { - throw new Error( - 'Failed to inject vendor-aliases plugin in @vitest/browser/index.js: pattern not found. ' + - 'This likely means vitest code has changed and the patch needs to be updated.', - ); - } - - // 2. Patch exclude list to add native deps - // Pattern: const exclude = ["vitest", ... - const excludePattern = /(const exclude = \[)(\n?\s*"vitest",)/; - // Exclude packages that: - // Packages to exclude from Vite's dependency pre-bundling (optimizeDeps.exclude) - const packagesToExclude = [ - // @vitest packages that need our resolveId plugin - '@vitest/browser', - '@vitest/ui', - '@vitest/ui/reporter', - '@vitest/mocker/node', // imports @voidzero-dev/vite-plus-core - - // Our package aliases - preserve module identity with init scripts - // This ensures both init scripts (loaded via /@fs/) and tests use the same page singleton - '@voidzero-dev/vite-plus-test', - '@voidzero-dev/vite-plus-test/browser', - '@voidzero-dev/vite-plus-test/browser/context', - 'vite-plus/test', - 'vite-plus/test/browser', - 'vite-plus/test/browser/context', - - // Node.js only packages - 'vite', - '@voidzero-dev/vite-plus-core', - '@voidzero-dev/vite-plus-core/module-runner', - - // Native bindings - 'lightningcss', - '@tailwindcss/oxide', - 'tailwindcss', // pulls in @tailwindcss/oxide - ]; - - const excludeListStr = packagesToExclude.map((pkg) => `"${pkg}"`).join(',\n '); - const excludeReplacement = `$1\n ${excludeListStr},$2`; - if (excludePattern.test(content)) { - content = content.replace(excludePattern, excludeReplacement); - console.log(' Patched exclude list with native deps'); - } else { - throw new Error( - 'Failed to patch exclude list in @vitest/browser/index.js: pattern not found. ' + - 'This likely means vitest code has changed and the patch needs to be updated.', - ); - } - - // 3. Remove include patterns that reference bundled deps - // These patterns like "vitest > expect-type" don't work with our bundled setup - // since the deps are already bundled into vendor files - const includePatterns = [ - '"vitest > expect-type"', - '"vitest > @vitest/snapshot > magic-string"', - '"vitest > @vitest/expect > chai"', - ]; - for (const pattern of includePatterns) { - content = content.replace( - new RegExp(`\\s*${pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')},?`, 'g'), - '', - ); - } - console.log(' Removed bundled deps from include list'); - - // 4. Patch BrowserContext to also handle our package aliases as fallback - // This allows direct imports from our package without requiring vitest override - // Supports: vitest/browser, @voidzero-dev/vite-plus-test/browser, vite-plus/test/browser - const browserContextPattern = /if \(id === ID_CONTEXT\) \{/; - if (browserContextPattern.test(content)) { - content = content.replace( - browserContextPattern, - `if (id === ID_CONTEXT || id === "@voidzero-dev/vite-plus-test/browser" || id === "vite-plus/test/browser") {`, - ); - console.log(' Patched BrowserContext to handle package aliases'); - } else { - throw new Error( - 'Failed to patch BrowserContext in @vitest/browser/index.js: pattern not found. ' + - 'This likely means vitest code has changed and the patch needs to be updated.', - ); - } - - // 5. Patch version to use VP_VERSION, preventing the "Running mixed versions" warning - const versionPattern = /var version = "(\d+\.\d+\.\d+[^"]*)"/; - const beforeVersion = content; - content = content.replace(versionPattern, 'var version = process.env.VP_VERSION || "$1"'); - if (content === beforeVersion) { - throw new Error( - 'Failed to patch version in @vitest/browser/index.js: pattern not found. ' + - 'This likely means vitest code has changed and the patch needs to be updated.', - ); - } - console.log(' Patched version to use VP_VERSION env var'); - - await writeFile(browserIndexPath, content, 'utf-8'); - console.log(' Successfully patched @vitest/browser/index.js'); -} - -/** - * Patch browser provider locators.js files to use browser-safe imports. - * - * The original files import from '../browser/index.js' which includes Node.js server code. - * We need to change them to import from browser-safe files instead. - * - * Providers handled: - * - @vitest/browser-playwright: import { page, server } from '../browser/index.js'; - * - @vitest/browser-webdriverio: import { page, server, utils } from '../browser/index.js'; - * - @vitest/browser-preview: import { page, server, utils, userEvent } from '../browser/index.js'; - */ -async function patchBrowserProviderLocators() { - console.log('\nPatching browser provider locators.js files...'); - - const providers = [ - { name: 'browser-playwright', extraImports: [] as string[] }, - { name: 'browser-webdriverio', extraImports: ['utils'] }, - { name: 'browser-preview', extraImports: ['utils', 'userEvent'] }, - ]; - - for (const provider of providers) { - const locatorsPath = join(distDir, `@vitest/${provider.name}/locators.js`); - - try { - await stat(locatorsPath); - } catch { - console.log(` Warning: @vitest/${provider.name}/locators.js not found, skipping`); - continue; - } - - let content = await readFile(locatorsPath, 'utf-8'); - let patched = false; - - // 1. Patch the vitest/browser import to separate page (from context.js) and other imports - // After rewriteVitestImports(), the import is: import { page, server, ... } from '../browser/index.js'; - // We need: - // - page from '../browser/context.js' (browser-safe) - // - server removed (we'll use window.__vitest_worker__.config instead) - // - other imports (utils, userEvent) still from '../browser/index.js' - - if (provider.extraImports.length === 0) { - // playwright: just import page from context.js - const serverImportPattern = - /import \{ page, server \} from ['"]\.\.\/browser\/index\.js['"];?/; - if (serverImportPattern.test(content)) { - content = content.replace( - serverImportPattern, - `import { page } from '../browser/context.js';`, - ); - console.log(` [${provider.name}] Changed server import to browser-safe context import`); - patched = true; - } - } else { - // webdriverio/preview: import page from context.js, keep other imports from index.js - const extraImportsStr = provider.extraImports.join(', '); - const importPattern = new RegExp( - `import \\{ page, server, ${extraImportsStr} \\} from ['"]\\.\\./browser/index\\.js['"];?`, - ); - if (importPattern.test(content)) { - const replacement = `import { page } from '../browser/context.js';\nimport { ${extraImportsStr} } from '../browser/index.js';`; - content = content.replace(importPattern, replacement); - console.log( - ` [${provider.name}] Split imports: page from context.js, {${extraImportsStr}} from index.js`, - ); - patched = true; - } - } - - if (!patched) { - console.log(` Warning: [${provider.name}] Could not find server import to patch`); - } - - // 2. Replace all server.config references with browser-accessible window.__vitest_worker__.config - // This handles both: - // - server.config.browser.locators.testIdAttribute - // - server.config.browser.ui - const serverConfigPattern = /server\.config\./g; - const matchCount = (content.match(serverConfigPattern) || []).length; - if (matchCount > 0) { - content = content.replace(serverConfigPattern, `window.__vitest_worker__.config.`); - console.log( - ` [${provider.name}] Replaced ${matchCount} server.config references with window.__vitest_worker__.config`, - ); - } - - await writeFile(locatorsPath, content, 'utf-8'); - console.log(` Successfully patched @vitest/${provider.name}/locators.js`); - } -} - -/** - * Create browser-compat.js shim that re-exports @vitest/browser compatible symbols. - * This allows our package to be used as an override for @vitest/browser. - */ -async function createBrowserCompatShim() { - console.log('\nCreating browser-compat shim...'); - - const browserIndexPath = join(distDir, '@vitest/browser/index.js'); - - try { - await stat(browserIndexPath); - } catch { - console.log(' Warning: @vitest/browser/index.js not found, skipping'); - return; - } - - const browserSymbols = [ - 'resolveScreenshotPath', - 'defineBrowserProvider', - 'parseKeyDef', - 'defineBrowserCommand', - ]; - - const shimContent = `// Re-export @vitest/browser compatible symbols -// This allows this package to be used as an override for @vitest/browser -export { ${browserSymbols.join(', ')} } from './@vitest/browser/index.js'; -`; - - const shimPath = join(distDir, 'browser-compat.js'); - await writeFile(shimPath, shimContent, 'utf-8'); - console.log(` Created ${relative(projectDir, shimPath)}`); -} - -/** - * Create a browser-safe stub for module-runner. - * The real module-runner contains Node.js-only code (process.platform, Buffer, etc.) - * that causes browsers to hang when loaded. This stub provides empty/placeholder - * exports so that browser code can import without errors. - */ -async function createModuleRunnerStub() { - console.log('\nCreating browser-safe module-runner stub...'); - - const stubContent = `// Browser-safe stub for module-runner -// The real module-runner contains Node.js-only code that crashes browsers -// This stub provides placeholder exports for browser compatibility - -// Stub class - browser doesn't actually use these -export class EvaluatedModules { - constructor() { - this.idToModuleMap = new Map(); - this.fileToModulesMap = new Map(); - this.urlToIdModuleMap = new Map(); - } - getModuleById() { return undefined; } - getModulesByFile() { return []; } - getModuleByUrl() { return undefined; } - ensureModule() { return {}; } - invalidateModule() {} - clear() {} -} - -export class ModuleRunner { - constructor() {} - async import() { throw new Error('ModuleRunner is not available in browser'); } - evaluatedModules = new EvaluatedModules(); -} - -export class ESModulesEvaluator { - constructor() {} - async runExternalModule() { return {}; } - async runViteModule() { return {}; } -} - -// Stub functions -export function createDefaultImportMeta() { return {}; } -export function createNodeImportMeta() { return {}; } -export function createWebSocketModuleRunnerTransport() { return {}; } -export function normalizeModuleId(id) { return id; } - -// SSR-related constants (browser doesn't use these) -export const ssrDynamicImportKey = '__vite_ssr_dynamic_import__'; -export const ssrExportAllKey = '__vite_ssr_exportAll__'; -export const ssrExportNameKey = '__vite_ssr_export__'; -export const ssrImportKey = '__vite_ssr_import__'; -export const ssrImportMetaKey = '__vite_ssr_import_meta__'; -export const ssrModuleExportsKey = '__vite_ssr_exports__'; -`; - - const stubPath = join(distDir, 'module-runner-stub.js'); - await writeFile(stubPath, stubContent, 'utf-8'); - console.log(` Created ${relative(projectDir, stubPath)}`); -} - -/** - * Create a Node.js-specific entry that includes @vitest/browser symbols. - * Browser code will use index.js (no browser-provider imports) to avoid loading Node.js code. - * Node.js code (like @vitest/browser-playwright) will use index-node.js which includes - * the browser symbols needed for pnpm override compatibility. - * - * This separation is critical because @vitest/browser/index.js imports from vitest/node, - * which contains Node.js-only code (including __vite__injectQuery) that crashes browsers. - */ -async function createNodeEntry() { - console.log('\nCreating Node.js-specific entry for @vitest/browser override...'); - - const browserIndexPath = join(distDir, '@vitest/browser/index.js'); - - try { - await stat(browserIndexPath); - } catch { - console.log(' Warning: @vitest/browser/index.js not found, skipping'); - return; - } - - const browserSymbols = [ - 'resolveScreenshotPath', - 'defineBrowserProvider', - 'parseKeyDef', - 'defineBrowserCommand', - ]; - - // Create index-node.js that re-exports everything from index.js plus browser symbols - const nodeEntry = `// Node.js-specific entry that includes @vitest/browser provider symbols -// Browser code should use index.js which doesn't pull in Node.js-only code -export * from './index.js'; - -// Re-export @vitest/browser symbols for pnpm override compatibility -// These are only needed when this package overrides @vitest/browser in Node.js context -export { ${browserSymbols.join(', ')} } from './@vitest/browser/index.js'; -`; - - const nodeEntryPath = join(distDir, 'index-node.js'); - await writeFile(nodeEntryPath, nodeEntry, 'utf-8'); - console.log(` Created dist/index-node.js with @vitest/browser exports`); -} - -/** - * Copy ALL files from @vitest/browser's dist to our dist. - * The bundled code in dist/vendor/ calculates paths like: - * pkgRoot = resolve(import.meta.url, "../..") -> package root - * distRoot = resolve(pkgRoot, "dist") -> dist/ - * Then looks for client/ files at distRoot, so we copy to dist/ not dist/vendor/. - */ -async function copyBrowserClientFiles() { - console.log('\nCopying @vitest/browser files to dist...'); - - // Find @vitest/browser's dist directory - const vitestBrowserDist = resolve(projectDir, 'node_modules/@vitest/browser/dist'); - - // Check if it exists - try { - await stat(vitestBrowserDist); - } catch { - console.log(' Warning: @vitest/browser not installed, skipping'); - return; - } - - // Copy all files from @vitest/browser/dist to our dist/ - // The bundled code at dist/vendor/ resolves paths relative to dist/ - // Use recursive directory traversal to include dotfiles (glob doesn't handle them well) - let copiedCount = 0; - - // Rewrite imports in copied JS files to use our dist files - // The relative path depends on the file's location relative to dist/ - function rewriteImports(content: string, destPath: string): string { - const fileDir = parse(destPath).dir; - - // Calculate relative path from file location to vendor directory - const vendorPath = join(distDir, 'vendor'); - let relativeToVendor = relative(fileDir, vendorPath); - // Ensure path starts with ./ for relative imports - if (!relativeToVendor.startsWith('.')) { - relativeToVendor = './' + relativeToVendor; - } - - // Calculate relative path from file location to dist directory - let relativeToDist = relative(fileDir, distDir); - if (!relativeToDist.startsWith('.')) { - relativeToDist = './' + relativeToDist; - } - - // Rewrite @vitest/* imports to use our copied @vitest files - for (const [pkg, distPath] of Object.entries(VITEST_PACKAGE_TO_PATH)) { - if (!pkg.startsWith('@vitest/')) { - continue; - } - // Pattern: from"@vitest/runner" or from "@vitest/runner" - const importPattern = new RegExp(`from\\s*["']${pkg.replace('/', '\\/')}["']`, 'g'); - content = content.replace(importPattern, `from"${relativeToDist}/${distPath}"`); - } - - // Rewrite vitest/* subpath imports to use our dist files - // These are the actual entry points for vitest's browser-safe exports - const vitestSubpathRewrites: Record = { - 'vitest/browser': `${relativeToDist}/context.js`, // vitest/browser exports context API - 'vitest/internal/browser': `${relativeToDist}/browser.js`, - 'vitest/runners': `${relativeToDist}/runners.js`, - }; - for (const [specifier, destFile] of Object.entries(vitestSubpathRewrites)) { - const importPattern = new RegExp(`from\\s*["']${specifier.replace('/', '\\/')}["']`, 'g'); - content = content.replace(importPattern, `from"${destFile}"`); - } - - // Special handling for @vitest/browser/client -> our client.js - // This is needed because the browser client files import from @vitest/browser/client - const browserClientPattern = /from\s*["']@vitest\/browser\/client["']/g; - content = content.replace(browserClientPattern, `from"${relativeToDist}/client.js"`); - - // Handle imports from ./index.js which is Node.js-only code - // In browser context, 'server' should read from __vitest_browser_runner__ at runtime - // Replace: import{server}from'./index.js' with a browser-safe stub - const serverStub = `const server = { - get browser() { return window.__vitest_browser_runner__?.config?.browser?.name; }, - get config() { return window.__vitest_browser_runner__?.config || {}; }, - get commands() { return window.__vitest_browser_runner__?.commands || {}; }, - get provider() { return window.__vitest_browser_runner__?.provider; }, -};`; - content = content.replace( - /import\s*\{\s*server\s*\}\s*from\s*['"]\.\/index\.js['"];?/g, - serverStub, - ); - - // Remove side-effect imports from ./index.js (Node.js-only) - // Pattern: import'./index.js'; at the end of an import statement - content = content.replace(/import\s*['"]\.\/index\.js['"];?/g, ''); - - return content; - } - - async function copyDirRecursive(srcDir: string, destDir: string) { - const entries = await readdir(srcDir, { withFileTypes: true }); - - for (const entry of entries) { - const srcPath = join(srcDir, entry.name); - const destPath = join(destDir, entry.name); - - if (entry.isDirectory()) { - await mkdir(destPath, { recursive: true }); - await copyDirRecursive(srcPath, destPath); - } else if (entry.isFile()) { - // Skip if file already exists (our bundled code takes precedence) - try { - await stat(destPath); - continue; - } catch { - // File doesn't exist, copy it - } - await mkdir(parse(destPath).dir, { recursive: true }); - - // For JS files, rewrite imports; otherwise just copy - if (entry.name.endsWith('.js')) { - let content = await readFile(srcPath, 'utf-8'); - content = rewriteImports(content, destPath); - await writeFile(destPath, content, 'utf-8'); - } else { - await copyFile(srcPath, destPath); - } - copiedCount++; - } - } - } - - await copyDirRecursive(vitestBrowserDist, distDir); - - // Create dummy.js for placeholder exports (matchers, utils) - const dummyContent = '// Placeholder for browser compatibility\nexport {};\n'; - await writeFile(join(distDir, 'dummy.js'), dummyContent, 'utf-8'); - - console.log(` Copied ${copiedCount} files from @vitest/browser to dist`); - - // Create vendor stubs for browser packages that aren't bundled - // Other dist files reference these vendor paths but we don't bundle browser packages - // to avoid Node.js code leakage. Instead, we create stubs that re-export from actual dist files. - console.log(' Creating vendor stubs for browser packages...'); - const browserVendorStubs = [ - { - vendorFile: 'vitest_browser.mjs', - // vitest/browser exports the context API (page, server, userEvent) - content: `// Stub for browser context - re-exports from our context.js -export * from '../context.js'; -`, - }, - { - vendorFile: 'vitest_internal_browser.mjs', - // vitest/internal/browser is browser.js - content: `// Stub for internal browser API - re-exports from our browser.js -export * from '../browser.js'; -`, - }, - { - vendorFile: 'vitest_runners.mjs', - // vitest/runners - content: `// Stub for runners - re-exports from our runners.js -export * from '../runners.js'; -`, - }, - { - vendorFile: 'vitest_runner.mjs', - // @vitest/runner (note: singular, not plural like vitest_runners which is vitest/runners) - content: `// Stub for @vitest/runner - re-exports from our copied @vitest/runner -export * from '../@vitest/runner/index.js'; -`, - }, - ]; - - for (const { vendorFile, content } of browserVendorStubs) { - const stubPath = join(distDir, 'vendor', vendorFile); - await writeFile(stubPath, content, 'utf-8'); - } - console.log(` Created ${browserVendorStubs.length} vendor stubs`); -} - -/** - * Create browser/ directory at package root with context files. - * The package exports "./browser" pointing to these files: - * - browser/context.js: Runtime guard (throws if used outside browser mode) - * - browser/context.d.ts: Re-exports types from dist/@vitest/browser/context.d.ts - * - * These files are NOT tracked in git (.gitignore excludes browser/) - * but ARE included in the package (package.json files: ["browser/**"]) - */ -async function createBrowserEntryFiles() { - console.log('\nCreating browser/ entry files...'); - - const browserDir = resolve(projectDir, 'browser'); - await mkdir(browserDir, { recursive: true }); - - // 1. Copy context.js from @vitest/browser (runtime guard) - const srcContextJs = resolve(projectDir, 'node_modules/@vitest/browser/context.js'); - const destContextJs = join(browserDir, 'context.js'); - await copyFile(srcContextJs, destContextJs); - console.log(' Created browser/context.js'); - - // 2. Create context.d.ts that re-exports from our bundled types - const contextDtsContent = `// Re-export browser context types from bundled @vitest/browser package -// This provides: page, userEvent, server, commands, utils, locators, cdp, Locator, etc. -// The bundled context.d.ts has imports rewritten to point to our dist files -export * from '../dist/@vitest/browser/context.d.ts' -`; - const destContextDts = join(browserDir, 'context.d.ts'); - await writeFile(destContextDts, contextDtsContent, 'utf-8'); - console.log(' Created browser/context.d.ts'); -} - -/** - * Patch module augmentations in global.d.*.d.ts files. - * - * The original vitest types use module augmentation like: - * declare module "@vitest/expect" { interface Assertion { toMatchSnapshot: ... } } - * - * Since we bundle @vitest/* packages inside dist/@vitest/*, the bare specifier - * "@vitest/expect" doesn't exist as a package for consumers. This breaks the - * module augmentation - TypeScript can't find @vitest/expect to augment. - * - * The fix has two parts: - * 1. Change module augmentation to use relative paths that TypeScript CAN resolve: - * declare module "../@vitest/expect/index.js" { ... } - * 2. Merge augmented interface/type definitions into the target .d.ts files so that - * downstream DTS bundlers (rolldown) can resolve them without cross-file augmentation. - */ -async function patchModuleAugmentations() { - console.log('\nPatching module augmentations in global.d.*.d.ts files...'); - - const chunksDir = join(distDir, 'chunks'); - const globalDtsFiles: string[] = []; - - // Find all global.d.*.d.ts files - for await (const file of fsGlob(join(chunksDir, 'global.d.*.d.ts'))) { - globalDtsFiles.push(file); - } - - if (globalDtsFiles.length === 0) { - console.log(' No global.d.*.d.ts files found'); - return; - } - - // Module augmentation mappings: bare specifier -> [relative path, target .d.ts file] - const augmentationMappings: Record = { - '@vitest/expect': { - relativePath: '../@vitest/expect/index.js', - targetFile: join(distDir, '@vitest/expect/index.d.ts'), - }, - '@vitest/runner': { - relativePath: '../@vitest/runner/index.js', - targetFile: join(distDir, '@vitest/runner/utils.d.ts'), - }, - }; - - for (const file of globalDtsFiles) { - let content = await readFile(file, 'utf-8'); - let modified = false; - - for (const [bareSpecifier, { relativePath, targetFile }] of Object.entries( - augmentationMappings, - )) { - const oldPattern = `declare module "${bareSpecifier}"`; - - // Extract the augmentation block content using brace matching - const startIdx = content.indexOf(oldPattern); - const braceStart = startIdx !== -1 ? content.indexOf('{', startIdx) : -1; - if (braceStart === -1) { - continue; - } - - let depth = 0; - let braceEnd = -1; - for (let i = braceStart; i < content.length; i++) { - if (content[i] === '{') { - depth++; - } else if (content[i] === '}') { - depth--; - if (depth === 0) { - braceEnd = i; - break; - } - } - } - if (braceEnd === -1) { - continue; - } - - const innerContent = content.slice(braceStart + 1, braceEnd).trim(); - - // Merge only NEW type declarations into the target .d.ts file. - // Interfaces that already exist (e.g., ExpectStatic, Assertion, MatcherState) must NOT - // be re-declared, as that would shadow extends clauses and break call signatures. - if (innerContent && existsSync(targetFile)) { - let targetContent = await readFile(targetFile, 'utf-8'); - - // Extract individual interface blocks from the augmentation content - const interfaceRegex = /(?:export\s+)?interface\s+(\w+)(?:<[^>]*>)?\s*\{/g; - let match; - const newDeclarations: string[] = []; - - while ((match = interfaceRegex.exec(innerContent)) !== null) { - const name = match[1]; - // Only merge if this interface does NOT already exist in the target file. - // Check both direct declarations (interface Name) and re-exports (export type { Name }). - const hasDirectDecl = new RegExp(`\\binterface\\s+${name}\\b`).test(targetContent); - const exportTypeMatch = targetContent.match(/export\s+type\s*\{([^}]*)\}/); - const isReExported = - exportTypeMatch != null && new RegExp(`\\b${name}\\b`).test(exportTypeMatch[1]); - if (hasDirectDecl || isReExported) { - console.log( - ` Skipped existing interface "${name}" (already in ${basename(targetFile)})`, - ); - continue; - } - - // Extract this interface block using brace matching - const ifaceStart = match.index; - const ifaceBraceStart = innerContent.indexOf('{', ifaceStart); - let ifaceDepth = 0; - let ifaceBraceEnd = -1; - for (let i = ifaceBraceStart; i < innerContent.length; i++) { - if (innerContent[i] === '{') { - ifaceDepth++; - } else if (innerContent[i] === '}') { - ifaceDepth--; - if (ifaceDepth === 0) { - ifaceBraceEnd = i; - break; - } - } - } - if (ifaceBraceEnd === -1) { - continue; - } - - let block = innerContent.slice(ifaceStart, ifaceBraceEnd + 1).trim(); - if (!block.startsWith('export')) { - block = `export ${block}`; - } - newDeclarations.push(block); - console.log(` Merged new interface "${name}" into ${basename(targetFile)}`); - } - - if (newDeclarations.length > 0) { - targetContent += `\n// Merged from module augmentation: declare module "${bareSpecifier}"\n${newDeclarations.join('\n')}\n`; - await writeFile(targetFile, targetContent, 'utf-8'); - } - } - - // Rewrite declare module path to relative - const newPattern = `declare module "${relativePath}"`; - content = content.replaceAll(oldPattern, newPattern); - modified = true; - console.log(` Patched: ${bareSpecifier} -> ${relativePath} in ${basename(file)}`); - } - - if (modified) { - await writeFile(file, content, 'utf-8'); - } - } - - // Re-export BrowserCommands from context.d.ts (imported but not exported) - const contextDtsPath = join(distDir, '@vitest/browser/context.d.ts'); - if (existsSync(contextDtsPath)) { - let content = await readFile(contextDtsPath, 'utf-8'); - if ( - content.includes('BrowserCommands') && - !content.match(/export\s+(type\s+)?\{[^}]*BrowserCommands/) - ) { - content += '\nexport type { BrowserCommands };\n'; - await writeFile(contextDtsPath, content, 'utf-8'); - console.log(' Added BrowserCommands re-export to context.d.ts'); - } - } - - // Validate: ensure no duplicate top-level interface declarations were introduced by merging. - // Only count interfaces at the module scope (not nested inside declare global, namespace, etc.) - for (const [bareSpecifier, { targetFile }] of Object.entries(augmentationMappings)) { - if (!existsSync(targetFile)) { - continue; - } - const finalContent = await readFile(targetFile, 'utf-8'); - - // Extract top-level interface names by tracking brace depth - const topLevelInterfaces: string[] = []; - let depth = 0; - for (let i = 0; i < finalContent.length; i++) { - if (finalContent[i] === '{') { - depth++; - } else if (finalContent[i] === '}') { - depth--; - } else if (depth === 0) { - const remaining = finalContent.slice(i); - const m = remaining.match(/^interface\s+(\w+)/); - if (m) { - topLevelInterfaces.push(m[1]); - i += m[0].length - 1; - } - } - } - - const counts = new Map(); - for (const name of topLevelInterfaces) { - counts.set(name, (counts.get(name) || 0) + 1); - } - - for (const [name, count] of counts) { - if (count > 1) { - throw new Error( - `Interface "${name}" is declared ${count} times at top level in ${basename(targetFile)}. ` + - `Module augmentation merge for "${bareSpecifier}" likely created a duplicate ` + - `declaration that will shadow extends clauses and break type signatures.`, - ); - } - } - } -} - -/** - * Add triple-slash reference to @types/chai in @vitest/expect types. - * - * The @vitest/expect types use the Chai namespace (e.g., Chai.Assertion) which - * is defined in @types/chai. Without a reference directive, TypeScript won't - * automatically find the Chai types, causing the `not` property and other - * chai-specific features to be missing from the Assertion interface. - */ -async function patchChaiTypeReference() { - console.log('\nAdding @types/chai reference to @vitest/expect types...'); - - const expectIndexDts = join(distDir, '@vitest/expect/index.d.ts'); - - let content = await readFile(expectIndexDts, 'utf-8'); - - // Check if reference already exists - if (content.includes('/// \n${content}`; - - await writeFile(expectIndexDts, content, 'utf-8'); - console.log(' Added /// to @vitest/expect/index.d.ts'); -} - -/** - * Patch the vitest mocker to recognize @voidzero-dev packages as valid sources for vi/vitest. - * - * The mocker's hoistMocks function checks if `vi` is imported from the 'vitest' module. - * When users import from 'vite-plus/test' instead, the mocker doesn't - * recognize it and throws "There are some problems in resolving the mocks API". - * - * This patch modifies the equality check to also accept our package names: - * - vite-plus/test - * - @voidzero-dev/vite-plus-test - */ -async function patchMockerHoistedModule() { - console.log('\nPatching vitest mocker to recognize @voidzero-dev packages...'); - - // The hoistedModule check may be in node.js or chunk-hoistMocks.js depending on the vitest version - const candidateFiles = [ - join(distDir, '@vitest/mocker/node.js'), - join(distDir, '@vitest/mocker/chunk-hoistMocks.js'), - ]; - - // Find and replace the hoistedModule check - // Original: if (hoistedModule === source) { - // New: if (hoistedModule === source || source === "vite-plus/test" || source === "@voidzero-dev/vite-plus-test") { - const originalCheck = 'if (hoistedModule === source) {'; - const newCheck = - 'if (hoistedModule === source || source === "vite-plus/test" || source === "@voidzero-dev/vite-plus-test") {'; - - let patched = false; - for (const candidatePath of candidateFiles) { - let content: string; - try { - content = await readFile(candidatePath, 'utf-8'); - } catch { - continue; - } - if (content.includes(originalCheck)) { - content = content.replace(originalCheck, newCheck); - await writeFile(candidatePath, content, 'utf-8'); - console.log(` Patched hoistMocks to recognize @voidzero-dev packages in ${candidatePath}`); - patched = true; - break; - } - } - - if (!patched) { - throw new Error( - 'Could not find hoistedModule check to patch in @vitest/mocker. ' + - 'This likely means vitest code has changed and the patch needs to be updated.', - ); - } -} - -/** - * Patch vitest's ModuleRunnerTransform plugin to automatically add known - * packages that use `expect.extend()` internally to `server.deps.inline`. - * - * When third-party libraries (e.g., @testing-library/jest-dom) call - * `require('vitest').expect.extend(matchers)`, the npm override causes - * a separate module instance to be created, so matchers are registered - * on a different `chai` instance than the one used by the test runner. - * - * By inlining these packages via `server.deps.inline`, the Vite module - * runner processes them through its transform pipeline, ensuring they - * share the same module instance as the test runner. - * - * See: https://github.com/voidzero-dev/vite-plus/issues/897 - */ -async function patchServerDepsInline() { - console.log('\nPatching server.deps.inline for expect.extend compatibility...'); - - let cliApiChunk: string | undefined; - for await (const chunk of fsGlob(join(distDir, 'chunks/cli-api.*.js'))) { - cliApiChunk = chunk; - break; - } - - if (!cliApiChunk) { - throw new Error('cli-api chunk not found for patchServerDepsInline'); - } - - let content = await readFile(cliApiChunk, 'utf-8'); - - // Packages that internally call expect.extend() and break under npm override. - // These must be inlined so they share the same vitest module instance. - const inlinePackages = ['@testing-library/jest-dom', '@storybook/test', 'jest-extended']; - - // Find the configResolved handler in ModuleRunnerTransform (vitest:environments-module-runner) - // and inject our inline packages after the existing server.deps.inline logic. - const original = `if (external.length) { - testConfig.server.deps.external ??= []; - testConfig.server.deps.external.push(...external); - }`; - - const patched = `if (external.length) { - testConfig.server.deps.external ??= []; - testConfig.server.deps.external.push(...external); - } - // Auto-inline packages that use expect.extend() internally (#897) - // Only inline packages that are actually installed in the project. - if (testConfig.server.deps.inline !== true) { - testConfig.server.deps.inline ??= []; - if (Array.isArray(testConfig.server.deps.inline)) { - const _require = createRequire(config.root + "/package.json"); - const autoInline = ${JSON.stringify(inlinePackages)}; - for (const pkg of autoInline) { - if (testConfig.server.deps.inline.includes(pkg)) continue; - try { - _require.resolve(pkg); - testConfig.server.deps.inline.push(pkg); - } catch { - // Package not installed in the project — skip silently - } - } - } - }`; - - if (!content.includes(original)) { - throw new Error( - 'Could not find server.deps.external pattern in ' + - cliApiChunk + - '. This likely means vitest code has changed and the patch needs to be updated.', - ); - } - - content = content.replace(original, patched); - await writeFile(cliApiChunk, content, 'utf-8'); - console.log(` Added auto-inline for: ${inlinePackages.join(', ')}`); -} - -/** - * Create /plugins/* exports for all copied @vitest/* packages. - * This allows pnpm overrides to redirect @vitest/* imports to our copied versions. - * e.g., @vitest/runner -> vitest/plugins/runner - * @vitest/utils/error -> vitest/plugins/utils-error - */ -async function createPluginExports() { - console.log('\nCreating plugin exports for @vitest/* packages...'); - - const pluginsDir = join(distDir, 'plugins'); - // Clean up stale plugin files from previous builds - await rm(pluginsDir, { recursive: true, force: true }); - await mkdir(pluginsDir, { recursive: true }); - - const createdExports: Array<{ exportPath: string; shimFile: string }> = []; - - for (const [pkg, distPath] of Object.entries(VITEST_PACKAGE_TO_PATH)) { - // Only create exports for @vitest/* packages - if (!pkg.startsWith('@vitest/')) { - continue; - } - // Convert @vitest/runner -> runner, @vitest/utils/error -> utils-error - // @vitest/utils/source-map/node -> utils-source-map-node - const exportName = pkg.replace('@vitest/', '').replaceAll('/', '-'); - const shimFileName = `${exportName}.mjs`; - const shimPath = join(pluginsDir, shimFileName); - - // Create the shim file that re-exports everything from @vitest/ - const shimContent = `// Re-export ${pkg} from copied @vitest package -export * from '../${distPath}'; -`; - - await writeFile(shimPath, shimContent, 'utf-8'); - createdExports.push({ - exportPath: `./plugins/${exportName}`, - shimFile: `./dist/plugins/${shimFileName}`, - }); - console.log(` Created plugins/${shimFileName} -> ${distPath}`); - } - - return createdExports; -} - -/** - * Validate that all external dependencies in dist are listed in package.json - */ -async function validateExternalDeps() { - console.log('\nValidating external dependencies...'); - - // Collect all declared dependencies - const declaredDeps = new Set([ - ...Object.keys(pkg.dependencies || {}), - ...Object.keys(pkg.peerDependencies || {}), - ]); - - // Also include self-references - declaredDeps.add(pkg.name); - declaredDeps.add('vitest'); // Self-reference via vitest name - - // Collect all external specifiers from ALL dist files (including vendor) - const externalSpecifiers = new Map>(); // specifier -> files - - const allJsFiles = fsGlob(join(distDir, '**/*.{js,mjs,cjs}')); - - for await (const file of allJsFiles) { - const content = await readFile(file, 'utf-8'); - const isCjs = file.endsWith('.cjs'); - - // Parse with oxc-parser - const result = parseSync(file, content, { - sourceType: isCjs ? 'script' : 'module', - }); - - const specifiers = new Set(); - - // Collect ESM static imports - for (const imp of result.module.staticImports) { - specifiers.add(imp.moduleRequest.value); - } - - // Collect ESM static exports (re-exports) - for (const exp of result.module.staticExports) { - for (const entry of exp.entries) { - if (entry.moduleRequest) { - specifiers.add(entry.moduleRequest.value); - } - } - } - - // Collect dynamic imports (only string literals) - for (const dynImp of result.module.dynamicImports) { - const rawText = content.slice(dynImp.moduleRequest.start, dynImp.moduleRequest.end); - if ( - (rawText.startsWith("'") && rawText.endsWith("'")) || - (rawText.startsWith('"') && rawText.endsWith('"')) - ) { - specifiers.add(rawText.slice(1, -1)); - } - } - - // For CJS files, also scan for require() calls - if (isCjs) { - const requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g; - let match; - while ((match = requireRegex.exec(content)) !== null) { - specifiers.add(match[1]); - } - } - - // Filter and record external specifiers - for (const specifier of specifiers) { - // Skip relative paths - if (specifier.startsWith('.') || specifier.startsWith('/')) { - continue; - } - // Skip node built-ins - if (NODE_BUILTINS.has(specifier)) { - continue; - } - // Skip Node.js subpath imports - if (specifier.startsWith('#')) { - continue; - } - - // Get the package name (handle scoped packages and subpaths) - const packageName = getPackageName(specifier); - if (!packageName) { - continue; - } - - // Check if it's declared - if (declaredDeps.has(packageName)) { - continue; - } - // Check if it's in the blocklist (intentionally external) - if (EXTERNAL_BLOCKLIST.has(packageName) || EXTERNAL_BLOCKLIST.has(specifier)) { - continue; - } - - // Record undeclared external - if (!externalSpecifiers.has(specifier)) { - externalSpecifiers.set(specifier, new Set()); - } - externalSpecifiers.get(specifier)!.add(relative(distDir, file)); - } - } - - if (externalSpecifiers.size === 0) { - console.log(' ✓ All external dependencies are declared in package.json'); - return; - } - - // Group by package name - const byPackage = new Map>(); - for (const [specifier, _files] of externalSpecifiers) { - const packageName = getPackageName(specifier)!; - if (!byPackage.has(packageName)) { - byPackage.set(packageName, new Set()); - } - byPackage.get(packageName)!.add(specifier); - } - - console.log(`\n ⚠ Found ${byPackage.size} undeclared external dependencies:\n`); - for (const [packageName, specifiers] of byPackage.entries()) { - const files = externalSpecifiers.get([...specifiers][0])!; - console.log(` ${packageName}`); - for (const specifier of specifiers) { - if (specifier !== packageName) { - console.log(` - ${specifier}`); - } - } - console.log( - ` (used in: ${[...files].slice(0, 3).join(', ')}${files.size > 3 ? '...' : ''})`, - ); - } -} - -/** - * Extract the package name from a specifier (handles scoped packages and subpaths) - */ -function getPackageName(specifier: string): string | null { - // Scoped package: @scope/name or @scope/name/subpath - if (specifier.startsWith('@')) { - const parts = specifier.split('/'); - if (parts.length >= 2) { - return `${parts[0]}/${parts[1]}`; - } - return null; - } - // Regular package: name or name/subpath - const parts = specifier.split('/'); - return parts[0] || null; -} diff --git a/packages/test/package.json b/packages/test/package.json deleted file mode 100644 index bfd1f53909..0000000000 --- a/packages/test/package.json +++ /dev/null @@ -1,368 +0,0 @@ -{ - "name": "@voidzero-dev/vite-plus-test", - "version": "0.0.0", - "description": "The Unified Toolchain for the Web", - "homepage": "https://viteplus.dev/guide", - "bugs": { - "url": "https://github.com/voidzero-dev/vite-plus/issues" - }, - "license": "MIT", - "author": "VoidZero Inc.", - "repository": { - "type": "git", - "url": "git+https://github.com/voidzero-dev/vite-plus.git", - "directory": "packages/test" - }, - "files": [ - "*.cjs", - "*.cts", - "*.d.ts", - "*.mjs", - "browser/**", - "dist/**" - ], - "type": "module", - "sideEffects": false, - "main": "./dist/index.js", - "module": "./dist/index.js", - "types": "./dist/index.d.ts", - "imports": { - "#module-evaluator": { - "types": "./dist/module-evaluator.d.ts", - "default": "./dist/module-evaluator.js" - }, - "#nodejs-worker-loader": "./dist/nodejs-worker-loader.js" - }, - "exports": { - ".": { - "import": { - "types": "./dist/index.d.ts", - "browser": "./dist/index.js", - "node": "./dist/index-node.js", - "default": "./dist/index.js" - }, - "require": { - "types": "./index.d.cts", - "default": "./index.cjs" - } - }, - "./browser": { - "types": "./browser/context.d.ts", - "default": "./browser/context.js" - }, - "./package.json": "./package.json", - "./optional-types.js": { - "types": "./optional-types.d.ts" - }, - "./optional-runtime-types.js": { - "types": "./optional-runtime-types.d.ts" - }, - "./src/*": "./src/*", - "./globals": { - "types": "./globals.d.ts" - }, - "./jsdom": { - "types": "./jsdom.d.ts" - }, - "./importMeta": { - "types": "./importMeta.d.ts" - }, - "./import-meta": { - "types": "./import-meta.d.ts" - }, - "./node": { - "types": "./dist/node.d.ts", - "default": "./dist/node.js" - }, - "./internal/browser": { - "types": "./dist/browser.d.ts", - "default": "./dist/browser.js" - }, - "./runners": { - "types": "./dist/runners.d.ts", - "default": "./dist/runners.js" - }, - "./suite": { - "types": "./dist/suite.d.ts", - "default": "./dist/suite.js" - }, - "./environments": { - "types": "./dist/environments.d.ts", - "default": "./dist/environments.js" - }, - "./config": { - "types": "./config.d.ts", - "require": "./dist/config.cjs", - "default": "./dist/config.js" - }, - "./coverage": { - "types": "./coverage.d.ts", - "default": "./dist/coverage.js" - }, - "./reporters": { - "types": "./dist/reporters.d.ts", - "default": "./dist/reporters.js" - }, - "./snapshot": { - "types": "./dist/snapshot.d.ts", - "default": "./dist/snapshot.js" - }, - "./runtime": { - "types": "./dist/runtime.d.ts", - "default": "./dist/runtime.js" - }, - "./worker": { - "types": "./worker.d.ts", - "default": "./dist/worker.js" - }, - "./browser-compat": { - "default": "./dist/browser-compat.js" - }, - "./client": { - "default": "./dist/client.js" - }, - "./context": { - "types": "./browser/context.d.ts", - "default": "./dist/@vitest/browser/context.js" - }, - "./browser/context": { - "types": "./browser/context.d.ts", - "default": "./dist/@vitest/browser/context.js" - }, - "./locators": { - "default": "./dist/locators.js" - }, - "./matchers": { - "default": "./dist/dummy.js" - }, - "./utils": { - "default": "./dist/dummy.js" - }, - "./browser-playwright": { - "types": "./dist/@vitest/browser-playwright/index.d.ts", - "default": "./dist/@vitest/browser-playwright/index.js" - }, - "./browser-webdriverio": { - "types": "./dist/@vitest/browser-webdriverio/index.d.ts", - "default": "./dist/@vitest/browser-webdriverio/index.js" - }, - "./browser-preview": { - "types": "./dist/@vitest/browser-preview/index.d.ts", - "default": "./dist/@vitest/browser-preview/index.js" - }, - "./browser/providers/playwright": { - "types": "./dist/@vitest/browser-playwright/index.d.ts", - "default": "./dist/@vitest/browser-playwright/index.js" - }, - "./browser/providers/webdriverio": { - "types": "./dist/@vitest/browser-webdriverio/index.d.ts", - "default": "./dist/@vitest/browser-webdriverio/index.js" - }, - "./browser/providers/preview": { - "types": "./dist/@vitest/browser-preview/index.d.ts", - "default": "./dist/@vitest/browser-preview/index.js" - }, - "./plugins/runner": { - "default": "./dist/plugins/runner.mjs" - }, - "./plugins/runner-utils": { - "default": "./dist/plugins/runner-utils.mjs" - }, - "./plugins/runner-types": { - "default": "./dist/plugins/runner-types.mjs" - }, - "./plugins/utils": { - "default": "./dist/plugins/utils.mjs" - }, - "./plugins/utils-source-map": { - "default": "./dist/plugins/utils-source-map.mjs" - }, - "./plugins/utils-source-map-node": { - "default": "./dist/plugins/utils-source-map-node.mjs" - }, - "./plugins/utils-error": { - "default": "./dist/plugins/utils-error.mjs" - }, - "./plugins/utils-helpers": { - "default": "./dist/plugins/utils-helpers.mjs" - }, - "./plugins/utils-display": { - "default": "./dist/plugins/utils-display.mjs" - }, - "./plugins/utils-timers": { - "default": "./dist/plugins/utils-timers.mjs" - }, - "./plugins/utils-highlight": { - "default": "./dist/plugins/utils-highlight.mjs" - }, - "./plugins/utils-offset": { - "default": "./dist/plugins/utils-offset.mjs" - }, - "./plugins/utils-resolver": { - "default": "./dist/plugins/utils-resolver.mjs" - }, - "./plugins/utils-serialize": { - "default": "./dist/plugins/utils-serialize.mjs" - }, - "./plugins/utils-constants": { - "default": "./dist/plugins/utils-constants.mjs" - }, - "./plugins/utils-diff": { - "default": "./dist/plugins/utils-diff.mjs" - }, - "./plugins/spy": { - "default": "./dist/plugins/spy.mjs" - }, - "./plugins/expect": { - "default": "./dist/plugins/expect.mjs" - }, - "./plugins/snapshot": { - "default": "./dist/plugins/snapshot.mjs" - }, - "./plugins/snapshot-environment": { - "default": "./dist/plugins/snapshot-environment.mjs" - }, - "./plugins/snapshot-manager": { - "default": "./dist/plugins/snapshot-manager.mjs" - }, - "./plugins/mocker": { - "default": "./dist/plugins/mocker.mjs" - }, - "./plugins/mocker-node": { - "default": "./dist/plugins/mocker-node.mjs" - }, - "./plugins/mocker-browser": { - "default": "./dist/plugins/mocker-browser.mjs" - }, - "./plugins/mocker-redirect": { - "default": "./dist/plugins/mocker-redirect.mjs" - }, - "./plugins/mocker-transforms": { - "default": "./dist/plugins/mocker-transforms.mjs" - }, - "./plugins/mocker-automock": { - "default": "./dist/plugins/mocker-automock.mjs" - }, - "./plugins/mocker-register": { - "default": "./dist/plugins/mocker-register.mjs" - }, - "./plugins/pretty-format": { - "default": "./dist/plugins/pretty-format.mjs" - }, - "./plugins/browser": { - "default": "./dist/plugins/browser.mjs" - }, - "./plugins/browser-context": { - "default": "./dist/plugins/browser-context.mjs" - }, - "./plugins/browser-client": { - "default": "./dist/plugins/browser-client.mjs" - }, - "./plugins/browser-locators": { - "default": "./dist/plugins/browser-locators.mjs" - }, - "./plugins/browser-playwright": { - "default": "./dist/plugins/browser-playwright.mjs" - }, - "./plugins/browser-webdriverio": { - "default": "./dist/plugins/browser-webdriverio.mjs" - }, - "./plugins/browser-preview": { - "default": "./dist/plugins/browser-preview.mjs" - } - }, - "scripts": { - "build": "oxnode -C dev ./build.ts" - }, - "dependencies": { - "@standard-schema/spec": "^1.1.0", - "@types/chai": "^5.2.2", - "@voidzero-dev/vite-plus-core": "workspace:*", - "es-module-lexer": "^1.7.0", - "obug": "^2.1.1", - "pixelmatch": "^7.1.0", - "pngjs": "^7.0.0", - "sirv": "^3.0.2", - "std-env": "^4.0.0", - "tinybench": "^2.9.0", - "tinyexec": "^1.0.2", - "tinyglobby": "^0.2.15", - "ws": "^8.18.3" - }, - "devDependencies": { - "@blazediff/core": "1.9.1", - "@oxc-node/cli": "catalog:", - "@oxc-node/core": "catalog:", - "@vitest/browser": "4.1.5", - "@vitest/browser-playwright": "4.1.5", - "@vitest/browser-preview": "4.1.5", - "@vitest/browser-webdriverio": "4.1.5", - "@vitest/expect": "4.1.5", - "@vitest/mocker": "4.1.5", - "@vitest/pretty-format": "4.1.5", - "@vitest/runner": "4.1.5", - "@vitest/snapshot": "4.1.5", - "@vitest/spy": "4.1.5", - "@vitest/utils": "4.1.5", - "chai": "^6.2.1", - "convert-source-map": "^2.0.0", - "estree-walker": "^3.0.3", - "expect-type": "^1.2.2", - "magic-string": "^0.30.21", - "oxc-parser": "catalog:", - "oxfmt": "catalog:", - "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "rolldown": "workspace:*", - "rolldown-plugin-dts": "catalog:", - "tinyrainbow": "^3.1.0", - "vitest-dev": "^4.1.5", - "why-is-node-running": "^2.3.0" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@opentelemetry/api": "^1.9.0", - "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/coverage-istanbul": "4.1.5", - "@vitest/coverage-v8": "4.1.5", - "@vitest/ui": "4.1.5", - "happy-dom": "*", - "jsdom": "*", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@opentelemetry/api": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/coverage-istanbul": { - "optional": true - }, - "@vitest/coverage-v8": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - }, - "vite": { - "optional": false - } - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "bundledVersions": { - "vitest": "4.1.5" - } -} diff --git a/packages/test/tsconfig.json b/packages/test/tsconfig.json deleted file mode 100644 index 62406593a8..0000000000 --- a/packages/test/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "experimentalDecorators": true - }, - "files": [], - "include": [], - "exclude": ["**/*"] -} diff --git a/packages/tools/package.json b/packages/tools/package.json index 139901c821..a7751d531e 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -18,9 +18,9 @@ "@oxc-node/cli": "catalog:", "@oxc-node/core": "catalog:", "@types/semver": "catalog:", - "@voidzero-dev/vite-plus-test": "workspace:*", "minimatch": "catalog:", "semver": "catalog:", + "vitest": "catalog:", "yaml": "catalog:" } } diff --git a/packages/tools/src/__tests__/utils.spec.ts b/packages/tools/src/__tests__/utils.spec.ts index 8f72a2137e..852d450a39 100644 --- a/packages/tools/src/__tests__/utils.spec.ts +++ b/packages/tools/src/__tests__/utils.spec.ts @@ -3,7 +3,7 @@ import fs from 'node:fs'; import { homedir, tmpdir } from 'node:os'; import path from 'node:path'; -import { describe, expect, test } from '@voidzero-dev/vite-plus-test'; +import { describe, expect, test } from 'vitest'; import { isPassThroughEnv, replaceUnstableOutput } from '../utils.ts'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 54dddcf557..8af7905d35 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -87,6 +87,18 @@ catalogs: '@typescript/native-preview': specifier: 7.0.0-dev.20260122.2 version: 7.0.0-dev.20260122.2 + '@vitest/browser': + specifier: 4.1.5 + version: 4.1.5 + '@vitest/browser-playwright': + specifier: 4.1.5 + version: 4.1.5 + '@vitest/browser-preview': + specifier: 4.1.5 + version: 4.1.5 + '@vitest/browser-webdriverio': + specifier: 4.1.5 + version: 4.1.5 '@yarnpkg/fslib': specifier: ^3.1.3 version: 3.1.4 @@ -243,6 +255,9 @@ catalogs: validate-npm-package-name: specifier: ^7.0.2 version: 7.0.2 + vitest: + specifier: 4.1.5 + version: 4.1.5 vue: specifier: ^3.5.21 version: 3.5.34 @@ -260,8 +275,7 @@ overrides: '@rolldown/pluginutils': workspace:@rolldown/pluginutils@* rolldown: workspace:rolldown@* vite: workspace:@voidzero-dev/vite-plus-core@* - vitest: workspace:@voidzero-dev/vite-plus-test@* - vitest-dev: npm:vitest@^4.1.5 + vite-plus: workspace:vite-plus@* packageExtensionsChecksum: sha256-Tldxs3DhJEw/FFBonUidqhCBqApA0zxQnop3Y+BTO3U= @@ -323,11 +337,11 @@ importers: specifier: workspace:@voidzero-dev/vite-plus-core@* version: link:packages/core vite-plus: - specifier: workspace:* + specifier: workspace:vite-plus@* version: link:packages/cli vitest: - specifier: workspace:@voidzero-dev/vite-plus-test@* - version: link:packages/test + specifier: 'catalog:' + version: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.10.3)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) zod: specifier: 'catalog:' version: 4.3.5 @@ -340,12 +354,21 @@ importers: '@oxlint/plugins': specifier: 'catalog:' version: 1.61.0 + '@vitest/browser': + specifier: 'catalog:' + version: 4.1.5(vite@packages+core)(vitest@4.1.5) + '@vitest/browser-playwright': + specifier: 'catalog:' + version: 4.1.5(playwright@1.57.0)(vite@packages+core)(vitest@4.1.5) + '@vitest/browser-preview': + specifier: 'catalog:' + version: 4.1.5(vite@packages+core)(vitest@4.1.5) + '@vitest/browser-webdriverio': + specifier: 'catalog:' + version: 4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1) '@voidzero-dev/vite-plus-core': specifier: workspace:* version: link:../core - '@voidzero-dev/vite-plus-test': - specifier: workspace:* - version: link:../test oxfmt: specifier: 'catalog:' version: 0.48.0 @@ -355,6 +378,9 @@ importers: oxlint-tsgolint: specifier: 'catalog:' version: 0.22.1 + vitest: + specifier: 'catalog:' + version: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) devDependencies: '@napi-rs/cli': specifier: 'catalog:' @@ -603,160 +629,6 @@ importers: specifier: 'catalog:' version: 0.22.0(@arethetypeswrong/core@0.18.2)(@tsdown/css@0.22.0)(@tsdown/exe@0.22.0)(@typescript/native-preview@7.0.0-dev.20260122.2)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(oxc-resolver@11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0))(publint@0.3.19)(tsx@4.21.0)(typescript@6.0.2)(unplugin-unused@0.5.6)(unrun@0.2.37) - packages/test: - dependencies: - '@edge-runtime/vm': - specifier: '*' - version: 5.0.0 - '@opentelemetry/api': - specifier: ^1.9.0 - version: 1.9.0 - '@standard-schema/spec': - specifier: ^1.1.0 - version: 1.1.0 - '@types/chai': - specifier: ^5.2.2 - version: 5.2.3 - '@types/node': - specifier: ^20.0.0 || ^22.0.0 || >=24.0.0 - version: 24.12.2 - '@vitest/coverage-istanbul': - specifier: 4.1.5 - version: 4.1.5(vitest@4.1.5) - '@vitest/coverage-v8': - specifier: 4.1.5 - version: 4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5) - '@vitest/ui': - specifier: 4.1.5 - version: 4.1.5(vitest@4.1.5) - '@voidzero-dev/vite-plus-core': - specifier: workspace:* - version: link:../core - es-module-lexer: - specifier: ^1.7.0 - version: 1.7.0 - happy-dom: - specifier: '*' - version: 20.0.10 - jsdom: - specifier: '*' - version: 27.2.0 - obug: - specifier: ^2.1.1 - version: 2.1.1 - pixelmatch: - specifier: ^7.1.0 - version: 7.1.0 - pngjs: - specifier: ^7.0.0 - version: 7.0.0 - sirv: - specifier: ^3.0.2 - version: 3.0.2(patch_hash=c07c56eb72faea34341d465cde2314e89db472106ed378181e3447893af6bf95) - std-env: - specifier: ^4.0.0 - version: 4.0.0 - tinybench: - specifier: ^2.9.0 - version: 2.9.0 - tinyexec: - specifier: ^1.0.2 - version: 1.1.2 - tinyglobby: - specifier: ^0.2.15 - version: 0.2.16 - vite: - specifier: workspace:@voidzero-dev/vite-plus-core@* - version: link:../core - ws: - specifier: ^8.18.3 - version: 8.20.0 - devDependencies: - '@blazediff/core': - specifier: 1.9.1 - version: 1.9.1 - '@oxc-node/cli': - specifier: 'catalog:' - version: 0.1.0 - '@oxc-node/core': - specifier: 'catalog:' - version: 0.1.0 - '@vitest/browser': - specifier: 4.1.5 - version: 4.1.5(vite@packages+core)(vitest@4.1.5) - '@vitest/browser-playwright': - specifier: 4.1.5 - version: 4.1.5(playwright@1.57.0)(vite@packages+core)(vitest@4.1.5) - '@vitest/browser-preview': - specifier: 4.1.5 - version: 4.1.5(vite@packages+core)(vitest@4.1.5) - '@vitest/browser-webdriverio': - specifier: 4.1.5 - version: 4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1) - '@vitest/expect': - specifier: 4.1.5 - version: 4.1.5 - '@vitest/mocker': - specifier: 4.1.5 - version: 4.1.5(vite@packages+core) - '@vitest/pretty-format': - specifier: 4.1.5 - version: 4.1.5 - '@vitest/runner': - specifier: 4.1.5 - version: 4.1.5 - '@vitest/snapshot': - specifier: 4.1.5 - version: 4.1.5 - '@vitest/spy': - specifier: 4.1.5 - version: 4.1.5 - '@vitest/utils': - specifier: 4.1.5 - version: 4.1.5 - chai: - specifier: ^6.2.1 - version: 6.2.2 - convert-source-map: - specifier: ^2.0.0 - version: 2.0.0 - estree-walker: - specifier: ^3.0.3 - version: 3.0.3 - expect-type: - specifier: ^1.2.2 - version: 1.3.0 - magic-string: - specifier: ^0.30.21 - version: 0.30.21 - oxc-parser: - specifier: 'catalog:' - version: 0.129.0 - oxfmt: - specifier: 'catalog:' - version: 0.48.0 - pathe: - specifier: ^2.0.3 - version: 2.0.3 - picomatch: - specifier: ^4.0.3 - version: 4.0.4 - rolldown: - specifier: workspace:rolldown@* - version: link:../../rolldown/packages/rolldown - rolldown-plugin-dts: - specifier: 'catalog:' - version: 0.23.2(@typescript/native-preview@7.0.0-dev.20260122.2)(oxc-resolver@11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0))(rolldown@rolldown+packages+rolldown)(typescript@6.0.2) - tinyrainbow: - specifier: ^3.1.0 - version: 3.1.0 - vitest-dev: - specifier: npm:vitest@^4.1.5 - version: vitest@4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5(playwright@1.57.0)(vite@packages+core)(vitest@4.1.5))(@vitest/browser-preview@4.1.5(vite@packages+core)(vitest@4.1.5))(@vitest/browser-webdriverio@4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1))(@vitest/coverage-istanbul@4.1.5(vitest@4.1.5))(@vitest/coverage-v8@4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5))(@vitest/ui@4.1.5(vitest@4.1.5))(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) - why-is-node-running: - specifier: ^2.3.0 - version: 2.3.0 - packages/tools: dependencies: '@yarnpkg/fslib': @@ -775,15 +647,15 @@ importers: '@types/semver': specifier: 'catalog:' version: 7.7.1 - '@voidzero-dev/vite-plus-test': - specifier: workspace:* - version: link:../test minimatch: specifier: 'catalog:' version: 10.2.4 semver: specifier: 'catalog:' version: 7.7.4 + vitest: + specifier: 'catalog:' + version: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) yaml: specifier: 'catalog:' version: 2.8.2 @@ -821,8 +693,8 @@ importers: specifier: 'catalog:' version: 6.0.2 vite-plus: - specifier: ^0.1.13 - version: 0.1.13(@arethetypeswrong/core@0.18.2)(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@tsdown/css@0.21.4)(@tsdown/exe@0.21.4)(@types/node@24.10.3)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(esbuild@0.27.4)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.2.0)(less@4.4.2)(publint@0.3.19)(sass-embedded@1.99.0(source-map-js@1.2.1))(sass@1.99.0)(stylus@0.64.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.46.2)(tsx@4.21.0)(typescript@6.0.2)(unplugin-unused@0.5.6)(vite@packages+core)(yaml@2.8.2) + specifier: workspace:vite-plus@* + version: link:../packages/cli rolldown/packages/bench: dependencies: @@ -912,8 +784,8 @@ importers: specifier: 'catalog:' version: 6.0.2 vitest: - specifier: workspace:@voidzero-dev/vite-plus-test@* - version: link:../../../packages/test + specifier: 'catalog:' + version: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) rolldown/packages/rolldown: dependencies: @@ -1152,8 +1024,8 @@ importers: specifier: workspace:@voidzero-dev/vite-plus-core@* version: link:../packages/core vitest: - specifier: workspace:@voidzero-dev/vite-plus-test@* - version: link:../packages/test + specifier: ^4.1.5 + version: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) vite/packages/create-vite: devDependencies: @@ -1536,10 +1408,6 @@ packages: resolution: {integrity: sha512-vSH118/wwM/pLR38g/Sgk05sNtro6TlTJKuiMXDaZqPUfjTFcudpCOt00IhOfj+1BFAX+UFAlzCU+6WXr3GLFQ==} engines: {node: '>=6.9.0'} - '@babel/generator@8.0.0-rc.2': - resolution: {integrity: sha512-oCQ1IKPwkzCeJzAPb7Fv8rQ9k5+1sG8mf2uoHiMInPYvkRfrDJxbTIbH51U+jstlkghus0vAi3EBvkfvEsYNLQ==} - engines: {node: ^20.19.0 || >=22.12.0} - '@babel/generator@8.0.0-rc.3': resolution: {integrity: sha512-em37/13/nR320G4jab/nIIHZgc2Wz2y/D39lxnTyxB4/D/omPQncl/lSdlnJY1OhQcRGugTSIF2l/69o31C9dA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1627,10 +1495,6 @@ packages: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@8.0.0-rc.2': - resolution: {integrity: sha512-xExUBkuXWJjVuIbO7z6q7/BA9bgfJDEhVL0ggrggLMbg0IzCUWGT1hZGE8qUH7Il7/RD/a6cZ3AAFrrlp1LF/A==} - engines: {node: ^20.19.0 || >=22.12.0} - '@babel/helper-validator-identifier@8.0.0-rc.3': resolution: {integrity: sha512-8AWCJ2VJJyDFlGBep5GpaaQ9AAaE/FjAcrqI7jyssYhtL7WGV0DOKpJsQqM037xDbpRLHXsY8TwU7zDma7coOw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1656,11 +1520,6 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/parser@8.0.0-rc.2': - resolution: {integrity: sha512-29AhEtcq4x8Dp3T72qvUMZHx0OMXCj4Jy/TEReQa+KWLln524Cj1fWb3QFi0l/xSpptQBR6y9RNEXuxpFvwiUQ==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - '@babel/parser@8.0.0-rc.3': resolution: {integrity: sha512-B20dvP3MfNc/XS5KKCHy/oyWl5IA6Cn9YjXRdDlCjNmUFrjvLXMNUfQq/QUy9fnG2gYkKKcrto2YaF9B32ToOQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2088,10 +1947,6 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@babel/types@8.0.0-rc.2': - resolution: {integrity: sha512-91gAaWRznDwSX4E2tZ1YjBuIfnQVOFDCQ2r0Toby0gu4XEbyF623kXLMA8d4ZbCu+fINcrudkmEcwSUHgDDkNw==} - engines: {node: ^20.19.0 || >=22.12.0} - '@babel/types@8.0.0-rc.3': resolution: {integrity: sha512-mOm5ZrYmphGfqVWoH5YYMTITb3cDXsFgmvFlvkvWDMsR9X8RFnt7a0Wb6yNIdoFsiMO9WjYLq+U/FMtqIYAF8Q==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3717,17 +3572,10 @@ packages: cpu: [x64] os: [win32] - '@oxc-project/runtime@0.120.0': - resolution: {integrity: sha512-7fvACzS46TkHuzA+Tag8ac40qfwURXRTdc4AtyItF59AoNPOO/QjPMqPyvJH8CaUdGu0ntWDX1CCUNyLMxxX5g==} - engines: {node: ^20.19.0 || >=22.12.0} - '@oxc-project/runtime@0.129.0': resolution: {integrity: sha512-0+S67blQakgeNqoKGozOUp5rQBrz2ynXZ2QIINXZPiafsD0YL0UogB9hAWc1S7k6VSNwKYC/N7MqT0V6IzpHkQ==} engines: {node: ^20.19.0 || >=22.12.0} - '@oxc-project/types@0.120.0': - resolution: {integrity: sha512-k1YNu55DuvAip/MGE1FTsIuU3FUCn6v/ujG9V7Nq5Df/kX2CWb13hhwD0lmJGMGqE+bE1MXvv9SZVnMzEXlWcg==} - '@oxc-project/types@0.121.0': resolution: {integrity: sha512-CGtOARQb9tyv7ECgdAlFxi0Fv7lmzvmlm2rpD/RdijOO9rfk/JvB1CjT8EnoD+tjna/IYgKKw3IV7objRb+aYw==} @@ -3972,97 +3820,48 @@ packages: cpu: [x64] os: [win32] - '@oxfmt/binding-android-arm-eabi@0.41.0': - resolution: {integrity: sha512-REfrqeMKGkfMP+m/ScX4f5jJBSmVNYcpoDF8vP8f8eYPDuPGZmzp56NIUsYmx3h7f6NzC6cE3gqh8GDWrJHCKw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [android] - '@oxfmt/binding-android-arm-eabi@0.48.0': resolution: {integrity: sha512-uwqk+/KhQvBIpULD8SMM/zAafMRC/+DV/xsEQjkkIsJ/kLmEI/2bxonVowcYTiXqqZ/a0FEW8DPkZY3VvwELDA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxfmt/binding-android-arm64@0.41.0': - resolution: {integrity: sha512-s0b1dxNgb2KomspFV2LfogC2XtSJB42POXF4bMCLJyvQmAGos4ZtjGPfQreToQEaY0FQFjz3030ggI36rF1q5g==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [android] - '@oxfmt/binding-android-arm64@0.48.0': resolution: {integrity: sha512-VUCiKuXK5+McVssgHEJdrcGK7hRJzrRb36zm9/jwzMholyYt4BgXhw5Nm1V1DX6Ce717Zi/1jk432b/tgmQgtQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxfmt/binding-darwin-arm64@0.41.0': - resolution: {integrity: sha512-EGXGualADbv/ZmamE7/2DbsrYmjoPlAmHEpTL4vapLF4EfVD6fr8/uQDFnPJkUBjiSWFJZtFNsGeN1B6V3owmA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] - '@oxfmt/binding-darwin-arm64@0.48.0': resolution: {integrity: sha512-IkKp8rnIyQLW6Jt+6jragCbUVYSayk55lapiprLjIVvt4NczLyO/nwX2GgefLQ5iaBdfS8UEAFgCs/pLO6Cl0w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxfmt/binding-darwin-x64@0.41.0': - resolution: {integrity: sha512-WxySJEvdQQYMmyvISH3qDpTvoS0ebnIP63IMxLLWowJyPp/AAH0hdWtlo+iGNK5y3eVfa5jZguwNaQkDKWpGSw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] - '@oxfmt/binding-darwin-x64@0.48.0': resolution: {integrity: sha512-+aFuhsGIuvnoOjXyKVHMhPKJZR1kQkAl8QyrKoMlA7yJsSTC3N0Asl53La8TChSHhW8epToQ/Q0nvLmEmfNmLg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxfmt/binding-freebsd-x64@0.41.0': - resolution: {integrity: sha512-Y2kzMkv3U3oyuYaR4wTfGjOTYTXiFC/hXmG0yVASKkbh02BJkvD98Ij8bIevr45hNZ0DmZEgqiXF+9buD4yMYQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [freebsd] - '@oxfmt/binding-freebsd-x64@0.48.0': resolution: {integrity: sha512-fbqzQL8FjI9gGnktI7RIo0dksDziTAYBy7xlI7jU7eID5fxLF/25fS4Xj6GydD8Y5oWHL83U4NK160QaOAxtyg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxfmt/binding-linux-arm-gnueabihf@0.41.0': - resolution: {integrity: sha512-ptazDjdUyhket01IjPTT6ULS1KFuBfTUU97osTP96X5y/0oso+AgAaJzuH81oP0+XXyrWIHbRzozSAuQm4p48g==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - '@oxfmt/binding-linux-arm-gnueabihf@0.48.0': resolution: {integrity: sha512-hn4i0zhAyTiB3ZHjQfYUZkDvrbVkohw1S7pySWxWUoZ87HnkDoTFThj7QTxk40hNPOTUP0vHbPRNamFIv1HBJQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxfmt/binding-linux-arm-musleabihf@0.41.0': - resolution: {integrity: sha512-UkoL2OKxFD+56bPEBcdGn+4juTW4HRv/T6w1dIDLnvKKWr6DbarB/mtHXlADKlFiJubJz8pRkttOR7qjYR6lTA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - '@oxfmt/binding-linux-arm-musleabihf@0.48.0': resolution: {integrity: sha512-R4WBD9qF3QM9hqgdAa+fBGXmquTvDUujrPQ36t2Sjk8RPOSKGHDeN7l/khr10hqbQaOq9KCgPHG9ubNET/X/RQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxfmt/binding-linux-arm64-gnu@0.41.0': - resolution: {integrity: sha512-gofu0PuumSOHYczD8p62CPY4UF6ee+rSLZJdUXkpwxg6pILiwSDBIouPskjF/5nF3A7QZTz2O9KFNkNxxFN9tA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [glibc] - '@oxfmt/binding-linux-arm64-gnu@0.48.0': resolution: {integrity: sha512-5bVdwSwlm1M8wbYCorLOxWxUBw/8tBvHYyQNIfwWVPwOJaj5vg1APSGJQVpwJfV5VNE9PSrR91UKEpoNwHhqUA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4070,13 +3869,6 @@ packages: os: [linux] libc: [glibc] - '@oxfmt/binding-linux-arm64-musl@0.41.0': - resolution: {integrity: sha512-VfVZxL0+6RU86T8F8vKiDBa+iHsr8PAjQmKGBzSCAX70b6x+UOMFl+2dNihmKmUwqkCazCPfYjt6SuAPOeQJ3g==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [musl] - '@oxfmt/binding-linux-arm64-musl@0.48.0': resolution: {integrity: sha512-vCS3Fk7gFslTqE1lUE2IlroyVV7u/9SmMA/uBqDoshuck2psGWcjW0ePyPZI3rM3+qtf2pDaMVIKMHozraifuw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4084,13 +3876,6 @@ packages: os: [linux] libc: [musl] - '@oxfmt/binding-linux-ppc64-gnu@0.41.0': - resolution: {integrity: sha512-bwzokz2eGvdfJbc0i+zXMJ4BBjQPqg13jyWpEEZDOrBCQ91r8KeY2Mi2kUeuMTZNFXju+jcAbAbpyJxRGla0eg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [ppc64] - os: [linux] - libc: [glibc] - '@oxfmt/binding-linux-ppc64-gnu@0.48.0': resolution: {integrity: sha512-gKtfFfueUClXDumyoHUbymqRf7prHejOOyzJK0eIJn93GF9JBdFHdo60TM1ZBHxkEwZvjuOgHmKtneKbEOc/Eg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4098,13 +3883,6 @@ packages: os: [linux] libc: [glibc] - '@oxfmt/binding-linux-riscv64-gnu@0.41.0': - resolution: {integrity: sha512-POLM//PCH9uqDeNDwWL3b3DkMmI3oI2cU6hwc2lnztD1o7dzrQs3R9nq555BZ6wI7t2lyhT9CS+CRaz5X0XqLA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [riscv64] - os: [linux] - libc: [glibc] - '@oxfmt/binding-linux-riscv64-gnu@0.48.0': resolution: {integrity: sha512-SYt0UhOvZD/UwZz9sXq6J2uAw8o24f5VZpLB2DH01f6MevshmlgakQlZe2lwek2sZJkd07eLu7mZa0g7yeiw7Q==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4112,13 +3890,6 @@ packages: os: [linux] libc: [glibc] - '@oxfmt/binding-linux-riscv64-musl@0.41.0': - resolution: {integrity: sha512-NNK7PzhFqLUwx/G12Xtm6scGv7UITvyGdAR5Y+TlqsG+essnuRWR4jRNODWRjzLZod0T3SayRbnkSIWMBov33w==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [riscv64] - os: [linux] - libc: [musl] - '@oxfmt/binding-linux-riscv64-musl@0.48.0': resolution: {integrity: sha512-JLbrwck2AopG4ud/XklZO5N+qxGC7cS7ROvXZVNfx0MCLDDL2kGOLvzuWORkVjnjAM0CMAfIMU2zNBtQbM+4dw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4126,13 +3897,6 @@ packages: os: [linux] libc: [musl] - '@oxfmt/binding-linux-s390x-gnu@0.41.0': - resolution: {integrity: sha512-qVf/zDC5cN9eKe4qI/O/m445er1IRl6swsSl7jHkqmOSVfknwCe5JXitYjZca+V/cNJSU/xPlC5EFMabMMFDpw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [s390x] - os: [linux] - libc: [glibc] - '@oxfmt/binding-linux-s390x-gnu@0.48.0': resolution: {integrity: sha512-mdxt5L8OQLxkQH+JVpdC/lknZNe0lX4hlO3d8+xvw2wToo+iDrid9tiGOd5bmHfUVd5wVhrUry0qlu5vq66NkQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4140,13 +3904,6 @@ packages: os: [linux] libc: [glibc] - '@oxfmt/binding-linux-x64-gnu@0.41.0': - resolution: {integrity: sha512-ojxYWu7vUb6ysYqVCPHuAPVZHAI40gfZ0PDtZAMwVmh2f0V8ExpPIKoAKr7/8sNbAXJBBpZhs2coypIo2jJX4w==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [glibc] - '@oxfmt/binding-linux-x64-gnu@0.48.0': resolution: {integrity: sha512-oEz1BQwMrV7OMEFx/3VPDU3n9TM0AnxpktDYXjEg5i6nTX87wo18wSfBvkl4tzAICdKtoAQAdBIl7Y7hsPlx5w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4154,13 +3911,6 @@ packages: os: [linux] libc: [glibc] - '@oxfmt/binding-linux-x64-musl@0.41.0': - resolution: {integrity: sha512-O2exZLBxoCMIv2vlvcbkdedazJPTdG0VSup+0QUCfYQtx751zCZNboX2ZUOiQ/gDTdhtXvSiot0h6GEGkOyalA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [musl] - '@oxfmt/binding-linux-x64-musl@0.48.0': resolution: {integrity: sha512-g2SKTTurP5mWjd8Ecait0erYqmltL4IqW1EwttM25BxM6NiTt4ubobJYMR1uox1V2QgG4UfHH10CGRvWlUixjw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4168,205 +3918,102 @@ packages: os: [linux] libc: [musl] - '@oxfmt/binding-openharmony-arm64@0.41.0': - resolution: {integrity: sha512-N+31/VoL+z+NNBt8viy3I4NaIdPbiYeOnB884LKqvXldaE2dRztdPv3q5ipfZYv0RwFp7JfqS4I27K/DSHCakg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [openharmony] - '@oxfmt/binding-openharmony-arm64@0.48.0': resolution: {integrity: sha512-CIg24VgheEpvolHL2gQuax5qcQ602bRMHrJ9g8XsQr3iVj9aSPgopigBKuMqrXsupwkrU+RQCn5cG8PgFntR6w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxfmt/binding-win32-arm64-msvc@0.41.0': - resolution: {integrity: sha512-Z7NAtu/RN8kjCQ1y5oDD0nTAeRswh3GJ93qwcW51srmidP7XPBmZbLlwERu1W5veCevQJtPS9xmkpcDTYsGIwQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] - '@oxfmt/binding-win32-arm64-msvc@0.48.0': resolution: {integrity: sha512-zeaWkcxcEULwkGF3I/HgEvcDPN8buYDrxibBUa/IFh5Vmwyge+KpLO+hEwSovW349H0O/C0Z2kaFmEzEDm00/Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxfmt/binding-win32-ia32-msvc@0.41.0': - resolution: {integrity: sha512-uNxxP3l4bJ6VyzIeRqCmBU2Q0SkCFgIhvx9/9dJ9V8t/v+jP1IBsuaLwCXGR8JPHtkj4tFp+RHtUmU2ZYAUpMA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [ia32] - os: [win32] - '@oxfmt/binding-win32-ia32-msvc@0.48.0': resolution: {integrity: sha512-yiEKnIAGvx5CyZQOlMaNlZkAbwT7/Quk0j3WLt+PR5hK+qYjPTRRJYDfD77wCBPLvEYAG41v4KG3iL0H+uxoxg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxfmt/binding-win32-x64-msvc@0.41.0': - resolution: {integrity: sha512-49ZSpbZ1noozyPapE8SUOSm3IN0Ze4b5nkO+4+7fq6oEYQQJFhE0saj5k/Gg4oewVPdjn0L3ZFeWk2Vehjcw7A==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] - '@oxfmt/binding-win32-x64-msvc@0.48.0': resolution: {integrity: sha512-GSD2+7t2UoVMV2NgxXypa4bKewflPMAjYnF0Xw9/ht82ZfafAHhb8STwrEd7wlH2PFogt5zw3WVCxYJaHUdbeQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@oxlint-tsgolint/darwin-arm64@0.17.1': - resolution: {integrity: sha512-JNWNwyvSDcUQSBlQRl10XrCeNcN66TMvDw3gIDQeop5SNa1F7wFhsEx4zitYb7fGHwGh9095tsNttmuCaNXCbw==} - cpu: [arm64] - os: [darwin] - '@oxlint-tsgolint/darwin-arm64@0.22.1': resolution: {integrity: sha512-4150Lpgc1YM09GcjA6GSrra1JoPjC7aOpfywLjWEY4vW0Sd1qKzqHF1WRaiw0/qUZ40OATYdv3aRd7ipPkWQbw==} cpu: [arm64] os: [darwin] - '@oxlint-tsgolint/darwin-x64@0.17.1': - resolution: {integrity: sha512-SluNf6CW88pgGPqQUGC5GoK5qESWo2ct1PRDbza3vbf9SK2npx3igvylGQIgE9qYYOcjgnVdLOJ0+q0gItgUmQ==} - cpu: [x64] - os: [darwin] - '@oxlint-tsgolint/darwin-x64@0.22.1': resolution: {integrity: sha512-vFWcPWYOgZs4HWcgS1EjUZg33NLcNfEYU49KGImmCfZWkflENrmBYV4HN/C0YeAPum6ZZ/goPSvQrB/cOD+NfA==} cpu: [x64] os: [darwin] - '@oxlint-tsgolint/linux-arm64@0.17.1': - resolution: {integrity: sha512-BJxQ7/cdo2dNdGIBs2PIR6BaPA7cPfe+r1HE/uY+K7g2ygip+0LHB3GUO9GaNDZuWpsnDyjLYYowEGrVK8dokA==} - cpu: [arm64] - os: [linux] - '@oxlint-tsgolint/linux-arm64@0.22.1': resolution: {integrity: sha512-6LiUpP0Zir3+29FvBm7Y28q/dBjSHqTZ5MhG1Ckw4fGhI4cAvbcwXaKvbjx1TP7rRmBNOoq/M5xdpHjTb+GAew==} cpu: [arm64] os: [linux] - '@oxlint-tsgolint/linux-x64@0.17.1': - resolution: {integrity: sha512-s6UjmuaJbZ4zz/wJKdEw/s5mc0t41rgwxQJCSHPuzMumMK6ylrB7nydhDf8ObTtzhTIZdAS/2S/uayJmDcGbxw==} - cpu: [x64] - os: [linux] - '@oxlint-tsgolint/linux-x64@0.22.1': resolution: {integrity: sha512-fuX1hEQfpHauUbXADsfqVhRzrUrGabzGXbj5wsp2vKhV5uk/Rze8Mba9GdjFGECzvXudMGqHqxB4r6jGRdhxVA==} cpu: [x64] os: [linux] - '@oxlint-tsgolint/win32-arm64@0.17.1': - resolution: {integrity: sha512-EO/Oj0ixHX+UQdu9hM7YUzibZI888MvPUo/DF8lSxFBt4JNEt8qGkwJEbCYjB/1LhUNmPHzSw2Tr9dCFVfW9nw==} - cpu: [arm64] - os: [win32] - '@oxlint-tsgolint/win32-arm64@0.22.1': resolution: {integrity: sha512-8SZidAj+jrbZf9ZjBEYW0tiNZ+KasqB2zgW26qdiPpQSF/DzURnPmXz651IeA9YsmbVdHGIooEHUmev6QJdquA==} cpu: [arm64] os: [win32] - '@oxlint-tsgolint/win32-x64@0.17.1': - resolution: {integrity: sha512-jhv7XktAJ1sMRSb//yDYTauFSZ06H81i2SLEBPaSUKxSKoPMK8p1ACUJlnmwZX2MgapRLEj1Ml22B6+HiM2YIA==} - cpu: [x64] - os: [win32] - '@oxlint-tsgolint/win32-x64@0.22.1': resolution: {integrity: sha512-QweSk9H5lFh5Y+WUf2Kq/OAN88V6+62ZwGhP38gqdRotI90luXSMkruFTj7Q2rYrzH4ZVNaSqx7NY8JpSfIzqg==} cpu: [x64] os: [win32] - '@oxlint/binding-android-arm-eabi@1.56.0': - resolution: {integrity: sha512-IyfYPthZyiSKwAv/dLjeO18SaK8MxLI9Yss2JrRDyweQAkuL3LhEy7pwIwI7uA3KQc1Vdn20kdmj3q0oUIQL6A==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [android] - '@oxlint/binding-android-arm-eabi@1.63.0': resolution: {integrity: sha512-A9xLtQt7i0OA1PoB/meog6kikXI9CdwEp7ZwQqmgnpKn3G3b1orvTDy8CQ6T7w1HvDrgWGB78PkFKcWgibcTCg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxlint/binding-android-arm64@1.56.0': - resolution: {integrity: sha512-Ga5zYrzH6vc/VFxhn6MmyUnYEfy9vRpwTIks99mY3j6Nz30yYpIkWryI0QKPCgvGUtDSXVLEaMum5nA+WrNOSg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [android] - '@oxlint/binding-android-arm64@1.63.0': resolution: {integrity: sha512-SQo+ZMvdR9l3CxZp5W5gFNxSiDxclY6lOzzNpKYLF8asESpm3Pwumx0gER5T7aHLF1/2BAAtLD3DiDkdgy4V1A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxlint/binding-darwin-arm64@1.56.0': - resolution: {integrity: sha512-ogmbdJysnw/D4bDcpf1sPLpFThZ48lYp4aKYm10Z/6Nh1SON6NtnNhTNOlhEY296tDFItsZUz+2tgcSYqh8Eyw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] - '@oxlint/binding-darwin-arm64@1.63.0': resolution: {integrity: sha512-6W82XjJDTmMnjg30427l0dufpnyLoq7wEukKdM6/g2VIybRVuQiBVh43EA4b+UxZ3+tLcKm+Or/pXGNgLCEU8g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxlint/binding-darwin-x64@1.56.0': - resolution: {integrity: sha512-x8QE1h+RAtQ2g+3KPsP6Fk/tdz6zJQUv5c7fTrJxXV3GHOo+Ry5p/PsogU4U+iUZg0rj6hS+E4xi+mnwwlDCWQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] - '@oxlint/binding-darwin-x64@1.63.0': resolution: {integrity: sha512-CnWd/YCuVG5W1BYkjJEVbJG11o526O9qAwBEQM+nh8K19CRFUkFdROXCyYkGmroHEYQe4vgQ6+lh3550Lp35Xw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxlint/binding-freebsd-x64@1.56.0': - resolution: {integrity: sha512-6G+WMZvwJpMvY7my+/SHEjb7BTk/PFbePqLpmVmUJRIsJMy/UlyYqjpuh0RCgYYkPLcnXm1rUM04kbTk8yS1Yg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [freebsd] - '@oxlint/binding-freebsd-x64@1.63.0': resolution: {integrity: sha512-a4eZAqrmtajqcxfdAzC+l7g3PaE3V8hpAYqqeD3fTxLXOMFdK3eNTZrU80n4dDEVm0JXy1aL5PqvqWldBl6zYA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxlint/binding-linux-arm-gnueabihf@1.56.0': - resolution: {integrity: sha512-YYHBsk/sl7fYwQOok+6W5lBPeUEvisznV/HZD2IfZmF3Bns6cPC3Z0vCtSEOaAWTjYWN3jVsdu55jMxKlsdlhg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - '@oxlint/binding-linux-arm-gnueabihf@1.63.0': resolution: {integrity: sha512-tYUtU9TdbU3uXF5D62g5zXJ13iniFGhXQx5vp9cyEjGdbSAY3VdFBSaldYvyoDmgMZ0ZYuwQP1Y4t2Fhejwa0w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm-musleabihf@1.56.0': - resolution: {integrity: sha512-+AZK8rOUr78y8WT6XkDb04IbMRqauNV+vgT6f8ZLOH8wnpQ9i7Nol0XLxAu+Cq7Sb+J9wC0j6Km5hG8rj47/yQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - '@oxlint/binding-linux-arm-musleabihf@1.63.0': resolution: {integrity: sha512-I5r3twFf776UZg9dmRo2xbrKt00tTkORXEVe0ctg4vdTkQvJAjiCHxnbAU2HL1AiJ9cqADA76MAliuilsAWnvg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm64-gnu@1.56.0': - resolution: {integrity: sha512-urse2SnugwJRojUkGSSeH2LPMaje5Q50yQtvtL9HFckiyeqXzoFwOAZqD5TR29R2lq7UHidfFDM9EGcchcbb8A==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [glibc] - '@oxlint/binding-linux-arm64-gnu@1.63.0': resolution: {integrity: sha512-t7ltUkg6FFh4b564QyGir8xIj/QZbXu8FlcRkcyW9+ztr/mfRHlvUOFd95pJCXi9s/L5DrUeWWgpXRS+V+6igQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4374,13 +4021,6 @@ packages: os: [linux] libc: [glibc] - '@oxlint/binding-linux-arm64-musl@1.56.0': - resolution: {integrity: sha512-rkTZkBfJ4TYLjansjSzL6mgZOdN5IvUnSq3oNJSLwBcNvy3dlgQtpHPrRxrCEbbcp7oQ6If0tkNaqfOsphYZ9g==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [musl] - '@oxlint/binding-linux-arm64-musl@1.63.0': resolution: {integrity: sha512-Q5mmZy/XWjuYFUuQyYjOvZ5U/JkKEwnpir6hGxhh6HcdP0V/BKxLo8dqkfF/t7r7AguB17dfS/8+go5AQDRR6g==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4388,13 +4028,6 @@ packages: os: [linux] libc: [musl] - '@oxlint/binding-linux-ppc64-gnu@1.56.0': - resolution: {integrity: sha512-uqL1kMH3u69/e1CH2EJhP3CP28jw2ExLsku4o8RVAZ7fySo9zOyI2fy9pVlTAp4voBLVgzndXi3SgtdyCTa2aA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [ppc64] - os: [linux] - libc: [glibc] - '@oxlint/binding-linux-ppc64-gnu@1.63.0': resolution: {integrity: sha512-uBGtuZ0TzLB4x5wVa82HGNvYqY8buwDhyCnCP0R0gkk9szqVsP0MeTtD5HX7EsEuFIt+aYmYxuxeVxs3nTSwtQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4402,13 +4035,6 @@ packages: os: [linux] libc: [glibc] - '@oxlint/binding-linux-riscv64-gnu@1.56.0': - resolution: {integrity: sha512-j0CcMBOgV6KsRaBdsebIeiy7hCjEvq2KdEsiULf2LZqAq0v1M1lWjelhCV57LxsqaIGChXFuFJ0RiFrSRHPhSg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [riscv64] - os: [linux] - libc: [glibc] - '@oxlint/binding-linux-riscv64-gnu@1.63.0': resolution: {integrity: sha512-h4s6FwxE+9MeA181o0dnDwHP32Y/bG8EiB/vrD6Ib+AMt6haigDc/0bUtI/sLmQDBMJnUfaCmtSSrEAqjtEVrA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4416,13 +4042,6 @@ packages: os: [linux] libc: [glibc] - '@oxlint/binding-linux-riscv64-musl@1.56.0': - resolution: {integrity: sha512-7VDOiL8cDG3DQ/CY3yKjbV1c4YPvc4vH8qW09Vv+5ukq3l/Kcyr6XGCd5NvxUmxqDb2vjMpM+eW/4JrEEsUetA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [riscv64] - os: [linux] - libc: [musl] - '@oxlint/binding-linux-riscv64-musl@1.63.0': resolution: {integrity: sha512-2EaNcCBR8Mcjl5ARtuN3BdEpVkX7KpjSjMGZ/mJMIeaXgTtdz5ytg2VwygMSStA/k0ixfvZFoZOfjDEcouV5vQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4430,13 +4049,6 @@ packages: os: [linux] libc: [musl] - '@oxlint/binding-linux-s390x-gnu@1.56.0': - resolution: {integrity: sha512-JGRpX0M+ikD3WpwJ7vKcHKV6Kg0dT52BW2Eu2BupXotYeqGXBrbY+QPkAyKO6MNgKozyTNaRh3r7g+VWgyAQYQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [s390x] - os: [linux] - libc: [glibc] - '@oxlint/binding-linux-s390x-gnu@1.63.0': resolution: {integrity: sha512-p4hlf/fd7TrYYl3QrWWD0GocqJefwMu3cHQhmi2FvEB/YOvFb5DZN3SMBaPi7B1TM5DeypkEtrVib674q1KKPg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4444,13 +4056,6 @@ packages: os: [linux] libc: [glibc] - '@oxlint/binding-linux-x64-gnu@1.56.0': - resolution: {integrity: sha512-dNaICPvtmuxFP/VbqdofrLqdS3bM/AKJN3LMJD52si44ea7Be1cBk6NpfIahaysG9Uo+L98QKddU9CD5L8UHnQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [glibc] - '@oxlint/binding-linux-x64-gnu@1.63.0': resolution: {integrity: sha512-Vgq9rkRVcPcjbcH+ihYTfpeR7vCXfqpd+z5ItTGc0yYUV59L5ceHYN1iV4H9bKGV7Rn5hkVc7x3mSvHegduENA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4458,13 +4063,6 @@ packages: os: [linux] libc: [glibc] - '@oxlint/binding-linux-x64-musl@1.56.0': - resolution: {integrity: sha512-pF1vOtM+GuXmbklM1hV8WMsn6tCNPvkUzklj/Ej98JhlanbmA2RB1BILgOpwSuCTRTIYx2MXssmEyQQ90QF5aA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [musl] - '@oxlint/binding-linux-x64-musl@1.63.0': resolution: {integrity: sha512-3/Lkq/ncooA61rorrC+ZQed1Bc4VpGj+WnGsp58zmxKgvZ2vhreu+dcVyr3mX8NUpq7mfZ4gDDTou/yrF1Pd7A==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4472,48 +4070,24 @@ packages: os: [linux] libc: [musl] - '@oxlint/binding-openharmony-arm64@1.56.0': - resolution: {integrity: sha512-bp8NQ4RE6fDIFLa4bdBiOA+TAvkNkg+rslR+AvvjlLTYXLy9/uKAYLQudaQouWihLD/hgkrXIKKzXi5IXOewwg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [openharmony] - '@oxlint/binding-openharmony-arm64@1.63.0': resolution: {integrity: sha512-0/EdD/6hDkx5Mfd769PTjvEM8mZ/6Dfukp1dBCL/2PjlIVGEtYdNZyok6ChqYPsT9JcFnlQnUeQzO0/1L/oC9w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxlint/binding-win32-arm64-msvc@1.56.0': - resolution: {integrity: sha512-PxT4OJDfMOQBzo3OlzFb9gkoSD+n8qSBxyVq2wQSZIHFQYGEqIRTo9M0ZStvZm5fdhMqaVYpOnJvH2hUMEDk/g==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] - '@oxlint/binding-win32-arm64-msvc@1.63.0': resolution: {integrity: sha512-wb0CUkN8ngwPiRQBjD1Cj0LsHeNvm+Xt6YBHDMtj2DVQVD6Oj8Ri7g6BD+KICf6LaBqZlmzOvy6nF9E/8yyGOg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxlint/binding-win32-ia32-msvc@1.56.0': - resolution: {integrity: sha512-PTRy6sIEPqy2x8PTP1baBNReN/BNEFmde0L+mYeHmjXE1Vlcc9+I5nsqENsB2yAm5wLkzPoTNCMY/7AnabT4/A==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [ia32] - os: [win32] - '@oxlint/binding-win32-ia32-msvc@1.63.0': resolution: {integrity: sha512-BX5iq+ovdNlVYhSn5qPMUIT0uwAwt2lmEnCnzK+Gkhw4DovIvhGb96OFhV8yzQNUnQxn/xGkOR+X+BLrLDNm8w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxlint/binding-win32-x64-msvc@1.56.0': - resolution: {integrity: sha512-ZHa0clocjLmIDr+1LwoWtxRcoYniAvERotvwKUYKhH41NVfl0Y4LNbyQkwMZzwDvKklKGvGZ5+DAG58/Ik47tQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] - '@oxlint/binding-win32-x64-msvc@1.63.0': resolution: {integrity: sha512-QeN/WELOfsXMeYwxvfgQrl6CbVftYUCZsGXHjXQd5Trccm8+i4gmtxaOui4xbJQaiDlviF8F3yLSBloQUeFsfA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4943,28 +4517,6 @@ packages: sass-embedded: optional: true - '@tsdown/css@0.21.4': - resolution: {integrity: sha512-2aU44SVyShHmL6VSefFBB0H8OXPqGqd6KwZ4+SP88DyyM+kZ1nBqzs65xf+HCyL/1NnidQtpA1wWkZLKgLv2SA==} - engines: {node: '>=20.19.0'} - peerDependencies: - postcss: ^8.4.0 - postcss-import: ^16.0.0 - postcss-modules: ^6.0.0 - sass: '*' - sass-embedded: '*' - tsdown: 0.21.4 - peerDependenciesMeta: - postcss: - optional: true - postcss-import: - optional: true - postcss-modules: - optional: true - sass: - optional: true - sass-embedded: - optional: true - '@tsdown/css@0.22.0': resolution: {integrity: sha512-gpkuNYVwgibCotNlHqgn1TJ9qHcE8Tim1rwaiQR7Ee9Rjb9BDYLypraaGMxqZgR1gr8NGRLGtbIv3eJtt5MHbQ==} engines: {node: ^22.18.0 || >=24.0.0} @@ -4993,12 +4545,6 @@ packages: peerDependencies: tsdown: 0.21.10 - '@tsdown/exe@0.21.4': - resolution: {integrity: sha512-aTniFeV/OjKa5Dxie4dbXar2wr3U+jKoascd+0XcK5uGBcadpzLUisks48QKRq7wTW+BF9N7cI0UyGGmEzHysg==} - engines: {node: '>=20.19.0'} - peerDependencies: - tsdown: 0.21.4 - '@tsdown/exe@0.22.0': resolution: {integrity: sha512-xOs2WOgB9R4J2PUfReZPK8h6IgbOXXuJ9JTQiAh3fK6Njhh219fRqPtSEHkNpYRccKYf4Tn0+Zum5AIFeOp7ZA==} engines: {node: ^22.18.0 || >=24.0.0} @@ -5372,201 +4918,78 @@ packages: peerDependencies: vite: workspace:@voidzero-dev/vite-plus-core@* - '@vitejs/release-scripts@1.7.0': - resolution: {integrity: sha512-4C+eoDs6yp/6kmnfOtuOWK+Dq0W3ws0eCs9k7w50P4YD7z+gMRUIyDbs0sGsJ4GjxN1WsS3qNfTT7ZpimtgeyA==} - - '@vitest/browser-playwright@4.1.5': - resolution: {integrity: sha512-CWy0lBQJq97nionyJJdnaU4961IXTl43a7UCu5nHy51IoKxAt6PVIJLo+76rVl7KOOgcWHNkG4kbJu/pW7knvA==} - peerDependencies: - playwright: '*' - vitest: workspace:@voidzero-dev/vite-plus-test@* - - '@vitest/browser-preview@4.1.5': - resolution: {integrity: sha512-UnUeV6/ykOOmrHjtQkOj01p+DZbJD18pNopACcEwt6NY1naL6L+caR+phpzTB6Mmgr5NL+2LDyrITGeTEmM9fQ==} - peerDependencies: - vitest: workspace:@voidzero-dev/vite-plus-test@* - - '@vitest/browser-webdriverio@4.1.5': - resolution: {integrity: sha512-irkLM1yClclWZL38CnklUsywd+DkJXHXys+BGOL4A9qiV2h1riSrXu1E7XVuGaxXvsJ55cUlVyV7x5mw3pDR6A==} - peerDependencies: - vitest: workspace:@voidzero-dev/vite-plus-test@* - webdriverio: '*' - - '@vitest/browser@4.1.5': - resolution: {integrity: sha512-iCDGI8c4yg+xmjUg2VsygdAUSIIB4x5Rht/P68OXy1hPELKXHDkzh87lkuTcdYmemRChDkEpB426MmDjzC0ziA==} - peerDependencies: - vitest: workspace:@voidzero-dev/vite-plus-test@* - - '@vitest/coverage-istanbul@4.1.5': - resolution: {integrity: sha512-X4kQMDEWh9mA0IiLuigtdYv4kXe+W8KLTbucoz15lbyZRPAxT5l+hu0JizI7Am050+G9vQnB7QJNgYi2LnwV4w==} - peerDependencies: - vitest: workspace:@voidzero-dev/vite-plus-test@* - - '@vitest/coverage-v8@4.1.5': - resolution: {integrity: sha512-38C0/Ddb7HcRG0Z4/DUem8x57d2p9jYgp18mkaYswEOQBGsI1CG4f/hjm0ZCeaJfWhSZ4k7jgs29V1Zom7Ki9A==} - peerDependencies: - '@vitest/browser': 4.1.5 - vitest: workspace:@voidzero-dev/vite-plus-test@* - peerDependenciesMeta: - '@vitest/browser': - optional: true - - '@vitest/expect@4.1.5': - resolution: {integrity: sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==} - - '@vitest/mocker@4.1.5': - resolution: {integrity: sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==} - peerDependencies: - msw: ^2.4.9 - vite: workspace:@voidzero-dev/vite-plus-core@* - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - - '@vitest/pretty-format@4.1.5': - resolution: {integrity: sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==} - - '@vitest/runner@4.1.5': - resolution: {integrity: sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==} - - '@vitest/snapshot@4.1.5': - resolution: {integrity: sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==} - - '@vitest/spy@4.1.5': - resolution: {integrity: sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==} - - '@vitest/ui@4.1.5': - resolution: {integrity: sha512-3Z9HNFiV0IF1fk0JPiK+7kE1GcaIPefQQIBYur6PM5yFIq6agys3uqP/0t966e1wXfmjbRCHDe7qW236Xjwnag==} - peerDependencies: - vitest: workspace:@voidzero-dev/vite-plus-test@* - - '@vitest/utils@4.1.5': - resolution: {integrity: sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==} - - '@voidzero-dev/vite-plus-core@0.1.13': - resolution: {integrity: sha512-72dAIYgGrrmh4ap5Tbvzo0EYCrmVRoPQjz3NERpZ34CWCjFB8+WAyBkxG631Jz9/qC1TR/ZThjOKbdYXQ5z9Aw==} - engines: {node: ^20.19.0 || >=22.12.0} - peerDependencies: - '@arethetypeswrong/core': ^0.18.1 - '@tsdown/css': 0.21.4 - '@tsdown/exe': 0.21.4 - '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.1.0 - esbuild: ^0.27.0 - jiti: '>=1.21.0' - less: ^4.0.0 - publint: ^0.3.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: '>=0.54.8' - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - typescript: ^5.0.0 - unplugin-unused: ^0.5.0 - yaml: ^2.4.2 - peerDependenciesMeta: - '@arethetypeswrong/core': - optional: true - '@tsdown/css': - optional: true - '@tsdown/exe': - optional: true - '@types/node': - optional: true - '@vitejs/devtools': - optional: true - esbuild: - optional: true - jiti: - optional: true - less: - optional: true - publint: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - typescript: - optional: true - unplugin-unused: - optional: true - yaml: - optional: true + '@vitejs/release-scripts@1.7.0': + resolution: {integrity: sha512-4C+eoDs6yp/6kmnfOtuOWK+Dq0W3ws0eCs9k7w50P4YD7z+gMRUIyDbs0sGsJ4GjxN1WsS3qNfTT7ZpimtgeyA==} - '@voidzero-dev/vite-plus-darwin-arm64@0.1.13': - resolution: {integrity: sha512-GgQ5dW1VR/Vuc8cRDsdpLMdly2rHiq8ihNKIh1eu8hR85bDjDxE4DSXeadCDMWC0bHTjQiR1HqApzjoPYsVF/w==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] + '@vitest/browser-playwright@4.1.5': + resolution: {integrity: sha512-CWy0lBQJq97nionyJJdnaU4961IXTl43a7UCu5nHy51IoKxAt6PVIJLo+76rVl7KOOgcWHNkG4kbJu/pW7knvA==} + peerDependencies: + playwright: '*' + vitest: 4.1.5 - '@voidzero-dev/vite-plus-darwin-x64@0.1.13': - resolution: {integrity: sha512-X4ZXbjIhNg5jxEkPVn7kJZEVIvNiOCWztrY67nHD94yqsWLy2Hs7yo+DhrpEQihsnlZ1hRRtwDirdCncvEulUg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] + '@vitest/browser-preview@4.1.5': + resolution: {integrity: sha512-UnUeV6/ykOOmrHjtQkOj01p+DZbJD18pNopACcEwt6NY1naL6L+caR+phpzTB6Mmgr5NL+2LDyrITGeTEmM9fQ==} + peerDependencies: + vitest: 4.1.5 - '@voidzero-dev/vite-plus-linux-arm64-gnu@0.1.13': - resolution: {integrity: sha512-oPtwztuF1cierDWA68beais5mwm6dXsmOOvccn6ZHjNpKXig84LvgIoY4bMazA3Z0SE9nWqxmP0kePiO5SoiuA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - libc: [glibc] + '@vitest/browser-webdriverio@4.1.5': + resolution: {integrity: sha512-irkLM1yClclWZL38CnklUsywd+DkJXHXys+BGOL4A9qiV2h1riSrXu1E7XVuGaxXvsJ55cUlVyV7x5mw3pDR6A==} + peerDependencies: + vitest: 4.1.5 + webdriverio: '*' - '@voidzero-dev/vite-plus-linux-x64-gnu@0.1.13': - resolution: {integrity: sha512-RgNHwTXrnYjt60K0g083VxOjaJNXHvZXViBQd/oC7RUwGUvxuHkraq/4mWaI69Pffx2KpyykxgCrtmhWq5Tgjg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - libc: [glibc] + '@vitest/browser@4.1.5': + resolution: {integrity: sha512-iCDGI8c4yg+xmjUg2VsygdAUSIIB4x5Rht/P68OXy1hPELKXHDkzh87lkuTcdYmemRChDkEpB426MmDjzC0ziA==} + peerDependencies: + vitest: 4.1.5 - '@voidzero-dev/vite-plus-test@0.1.13': - resolution: {integrity: sha512-P3n9adJZsaIUGlgbzyT2YvlA1yr2lCYhNjrZsiLAKMVyQzk2D++ptTre3SnYf9j1TQeMP1VonRXGjtZhTf8wHg==} - engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + '@vitest/coverage-istanbul@4.1.5': + resolution: {integrity: sha512-X4kQMDEWh9mA0IiLuigtdYv4kXe+W8KLTbucoz15lbyZRPAxT5l+hu0JizI7Am050+G9vQnB7QJNgYi2LnwV4w==} peerDependencies: - '@edge-runtime/vm': '*' - '@opentelemetry/api': ^1.9.0 - '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/ui': 4.1.0 - happy-dom: '*' - jsdom: '*' - vite: workspace:@voidzero-dev/vite-plus-core@* + vitest: 4.1.5 + + '@vitest/coverage-v8@4.1.5': + resolution: {integrity: sha512-38C0/Ddb7HcRG0Z4/DUem8x57d2p9jYgp18mkaYswEOQBGsI1CG4f/hjm0ZCeaJfWhSZ4k7jgs29V1Zom7Ki9A==} + peerDependencies: + '@vitest/browser': 4.1.5 + vitest: 4.1.5 peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@opentelemetry/api': - optional: true - '@types/node': - optional: true - '@vitest/ui': + '@vitest/browser': optional: true - happy-dom: + + '@vitest/expect@4.1.5': + resolution: {integrity: sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==} + + '@vitest/mocker@4.1.5': + resolution: {integrity: sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==} + peerDependencies: + msw: ^2.4.9 + vite: workspace:@voidzero-dev/vite-plus-core@* + peerDependenciesMeta: + msw: optional: true - jsdom: + vite: optional: true - '@voidzero-dev/vite-plus-win32-arm64-msvc@0.1.13': - resolution: {integrity: sha512-+oygKTgglu0HkA4y9kFs8/BbHFsvShkHuL+8bK++Zek3x2ArKHRjCMgcYUXyj6nYufMIL2ba/Und7aHUK2ZGiQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] + '@vitest/pretty-format@4.1.5': + resolution: {integrity: sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==} - '@voidzero-dev/vite-plus-win32-x64-msvc@0.1.13': - resolution: {integrity: sha512-+7zTnX/HqYCaBKmSLHjmCXQBRSSIJ6EFry55+4C0R4AMyayfn9w3LL0/NuVeCNkG69u3FnkRuwkqdWpzxztoHQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] + '@vitest/runner@4.1.5': + resolution: {integrity: sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==} + + '@vitest/snapshot@4.1.5': + resolution: {integrity: sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==} + + '@vitest/spy@4.1.5': + resolution: {integrity: sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==} + + '@vitest/ui@4.1.5': + resolution: {integrity: sha512-3Z9HNFiV0IF1fk0JPiK+7kE1GcaIPefQQIBYur6PM5yFIq6agys3uqP/0t966e1wXfmjbRCHDe7qW236Xjwnag==} + peerDependencies: + vitest: 4.1.5 + + '@vitest/utils@4.1.5': + resolution: {integrity: sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==} '@vue-macros/common@3.1.2': resolution: {integrity: sha512-h9t4ArDdniO9ekYHAD95t9AZcAbb19lEGK+26iAjUODOIJKmObDNBSe4+6ELQAA3vtYiFPPBtHh7+cQCKi3Dng==} @@ -7049,10 +6472,6 @@ packages: import-meta-resolve@4.2.0: resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} - import-without-cache@0.2.5: - resolution: {integrity: sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A==} - engines: {node: '>=20.19.0'} - import-without-cache@0.3.3: resolution: {integrity: sha512-bDxwDdF04gm550DfZHgffvlX+9kUlcz32UD0AeBTmVPFiWkrexF2XVmiuFFbDhiFuP8fQkrkvI2KdSNPYWAXkQ==} engines: {node: '>=20.19.0'} @@ -7753,34 +7172,15 @@ packages: resolution: {integrity: sha512-RGQZ5pnvWEQmtb51IavGp8mQqyQAB7J+N1TFuXxfQEHwfXinwAkhWPU/VffIIjjUgR63IbpWFAewqIVxnQP87w==} engines: {node: ^20.19.0 || >=22.12.0} - oxfmt@0.41.0: - resolution: {integrity: sha512-sKLdJZdQ3bw6x9qKiT7+eID4MNEXlDHf5ZacfIircrq6Qwjk0L6t2/JQlZZrVHTXJawK3KaMuBoJnEJPcqCEdg==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - oxfmt@0.48.0: resolution: {integrity: sha512-AVaLh+7XeGx+R1zfFV+f6VV61nT2MWVJXVUDhbTm5LBWGyNt64xAyh3NYYyjeY2WykNt9AvqSQLPHcbWquYF9g==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - oxlint-tsgolint@0.17.1: - resolution: {integrity: sha512-gJc7hb1ZQFbWjRDYpu1XG+5IRdr1S/Jz/W2ohcpaqIXuDmHU0ujGiM0x05J0nIfwMF3HOEcANi/+j6T0Uecdpg==} - hasBin: true - oxlint-tsgolint@0.22.1: resolution: {integrity: sha512-YUSGSLUnoolsu8gxISEDio3q1rtsCozwfOzASUn3DT2mR2EeQ93uEEnen7s+6LpF+lyTQFln1pQfqwBh/fsVEg==} hasBin: true - oxlint@1.56.0: - resolution: {integrity: sha512-Q+5Mj5PVaH/R6/fhMMFzw4dT+KPB+kQW4kaL8FOIq7tfhlnEVp6+3lcWqFruuTNlUo9srZUW3qH7Id4pskeR6g==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - oxlint-tsgolint: '>=0.15.0' - peerDependenciesMeta: - oxlint-tsgolint: - optional: true - oxlint@1.63.0: resolution: {integrity: sha512-9TGXetdjgIHOJ9OiReomP7nnrMkV9HxC1xM2ramJSLQpzxjsAJtQwa4wqkJN2f/uCrqZuJseFuSlWDdvcruveg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -7925,10 +7325,6 @@ packages: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} - pixelmatch@7.1.0: - resolution: {integrity: sha512-1wrVzJ2STrpmONHKBy228LM1b84msXDUoAzVEl0R8Mz4Ce6EPr+IVtxm8+yvrqLYMHswREkjYFaMxnyGnaY3Ng==} - hasBin: true - pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} @@ -8251,25 +7647,6 @@ packages: rgb2hex@0.2.5: resolution: {integrity: sha512-22MOP1Rh7sAo1BZpDG6R5RFYzR2lYEgwq7HEmyW2qcsOqR2lQKmn+O//xV3YG/0rrhMC6KVX2hU+ZXuaw9a5bw==} - rolldown-plugin-dts@0.22.5: - resolution: {integrity: sha512-M/HXfM4cboo+jONx9Z0X+CUf3B5tCi7ni+kR5fUW50Fp9AlZk0oVLesibGWgCXDKFp5lpgQ9yhKoImUFjl3VZw==} - engines: {node: '>=20.19.0'} - peerDependencies: - '@ts-macro/tsc': ^0.3.6 - '@typescript/native-preview': '>=7.0.0-dev.20250601.1' - rolldown: workspace:rolldown@* - typescript: ^5.0.0 || ^6.0.0-beta - vue-tsc: ~3.2.0 - peerDependenciesMeta: - '@ts-macro/tsc': - optional: true - '@typescript/native-preview': - optional: true - typescript: - optional: true - vue-tsc: - optional: true - rolldown-plugin-dts@0.23.2: resolution: {integrity: sha512-PbSqLawLgZBGcOGT3yqWBGn4cX+wh2nt5FuBGdcMHyOhoukmjbhYAl8NT9sE4U38Cm9tqLOIQeOrvzeayM0DLQ==} engines: {node: '>=20.19.0'} @@ -8915,34 +8292,6 @@ packages: unplugin-unused: optional: true - tsdown@0.21.4: - resolution: {integrity: sha512-Q/kBi8SXkr4X6JI/NAZKZY1UuiEcbuXtIskL4tZCsgpDiEPM/2W6lC+OonNA31S+V3KsWedFvbFDBs23hvt+Aw==} - engines: {node: '>=20.19.0'} - hasBin: true - peerDependencies: - '@arethetypeswrong/core': ^0.18.1 - '@tsdown/css': 0.21.4 - '@tsdown/exe': 0.21.4 - '@vitejs/devtools': '*' - publint: ^0.3.0 - typescript: ^5.0.0 - unplugin-unused: ^0.5.0 - peerDependenciesMeta: - '@arethetypeswrong/core': - optional: true - '@tsdown/css': - optional: true - '@tsdown/exe': - optional: true - '@vitejs/devtools': - optional: true - publint: - optional: true - typescript: - optional: true - unplugin-unused: - optional: true - tsdown@0.22.0: resolution: {integrity: sha512-FgW0hHb27nGQA/+F3d5+U9wKXkfilk9DVkc5+7x/ZqF03g+Hoz/eeApT32jqxATt9eRoR+1jxk7MUMON+O4CXw==} engines: {node: ^22.18.0 || >=24.0.0} @@ -9259,11 +8608,6 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - vite-plus@0.1.13: - resolution: {integrity: sha512-DP87+eRFhYYDdcjm2nr3DOKt0cv6mIXCNXn+zc59YHgR0Wh7uL2E/55mjusJ7ajwcXenpGW+c4KPeoqhQAbhxg==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - vitest@4.1.5: resolution: {integrity: sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -9529,7 +8873,8 @@ packages: snapshots: - '@acemir/cssom@0.9.24': {} + '@acemir/cssom@0.9.24': + optional: true '@adobe/css-tools@4.3.3': {} @@ -9553,6 +8898,7 @@ snapshots: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 lru-cache: 11.2.7 + optional: true '@asamuzakjp/dom-selector@6.7.4': dependencies: @@ -9561,8 +8907,10 @@ snapshots: css-tree: 3.1.0 is-potential-custom-element-name: 1.0.1 lru-cache: 11.2.7 + optional: true - '@asamuzakjp/nwsapi@2.3.9': {} + '@asamuzakjp/nwsapi@2.3.9': + optional: true '@ast-grep/napi-darwin-arm64@0.42.1': optional: true @@ -9639,16 +8987,6 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - '@babel/generator@8.0.0-rc.2': - dependencies: - '@babel/parser': 8.0.0-rc.4 - '@babel/types': 8.0.0-rc.4 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - '@types/jsesc': 2.5.1 - jsesc: 3.1.0 - optional: true - '@babel/generator@8.0.0-rc.3': dependencies: '@babel/parser': 8.0.0-rc.4 @@ -9772,9 +9110,6 @@ snapshots: '@babel/helper-validator-identifier@7.28.5': {} - '@babel/helper-validator-identifier@8.0.0-rc.2': - optional: true - '@babel/helper-validator-identifier@8.0.0-rc.3': {} '@babel/helper-validator-identifier@8.0.0-rc.4': {} @@ -9798,11 +9133,6 @@ snapshots: dependencies: '@babel/types': 7.29.0 - '@babel/parser@8.0.0-rc.2': - dependencies: - '@babel/types': 8.0.0-rc.4 - optional: true - '@babel/parser@8.0.0-rc.3': dependencies: '@babel/types': 8.0.0-rc.4 @@ -10348,12 +9678,6 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@babel/types@8.0.0-rc.2': - dependencies: - '@babel/helper-string-parser': 8.0.0-rc.4 - '@babel/helper-validator-identifier': 8.0.0-rc.4 - optional: true - '@babel/types@8.0.0-rc.3': dependencies: '@babel/helper-string-parser': 8.0.0-rc.4 @@ -10364,7 +9688,8 @@ snapshots: '@babel/helper-string-parser': 8.0.0-rc.4 '@babel/helper-validator-identifier': 8.0.0-rc.4 - '@bcoe/v8-coverage@1.0.2': {} + '@bcoe/v8-coverage@1.0.2': + optional: true '@blazediff/core@1.9.1': {} @@ -10404,12 +9729,14 @@ snapshots: conventional-commits-filter: 5.0.0 conventional-commits-parser: 6.4.0 - '@csstools/color-helpers@5.1.0': {} + '@csstools/color-helpers@5.1.0': + optional: true '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 + optional: true '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: @@ -10417,20 +9744,26 @@ snapshots: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 + optional: true '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': dependencies: '@csstools/css-tokenizer': 3.0.4 + optional: true - '@csstools/css-syntax-patches-for-csstree@1.0.17': {} + '@csstools/css-syntax-patches-for-csstree@1.0.17': + optional: true - '@csstools/css-tokenizer@3.0.4': {} + '@csstools/css-tokenizer@3.0.4': + optional: true - '@edge-runtime/primitives@6.0.0': {} + '@edge-runtime/primitives@6.0.0': + optional: true '@edge-runtime/vm@5.0.0': dependencies: '@edge-runtime/primitives': 6.0.0 + optional: true '@emnapi/core@1.10.0': dependencies: @@ -10941,7 +10274,8 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 - '@istanbuljs/schema@0.1.3': {} + '@istanbuljs/schema@0.1.3': + optional: true '@jridgewell/gen-mapping@0.3.13': dependencies: @@ -11461,7 +10795,8 @@ snapshots: '@octokit/request-error': 7.1.0 '@octokit/webhooks-methods': 6.0.0 - '@opentelemetry/api@1.9.0': {} + '@opentelemetry/api@1.9.0': + optional: true '@oxc-node/cli@0.1.0': dependencies: @@ -11737,12 +11072,8 @@ snapshots: '@oxc-parser/binding-win32-x64-msvc@0.129.0': optional: true - '@oxc-project/runtime@0.120.0': {} - '@oxc-project/runtime@0.129.0': {} - '@oxc-project/types@0.120.0': {} - '@oxc-project/types@0.121.0': {} '@oxc-project/types@0.126.0': {} @@ -11878,267 +11209,135 @@ snapshots: '@oxc-transform/binding-win32-x64-msvc@0.129.0': optional: true - '@oxfmt/binding-android-arm-eabi@0.41.0': - optional: true - '@oxfmt/binding-android-arm-eabi@0.48.0': optional: true - '@oxfmt/binding-android-arm64@0.41.0': - optional: true - '@oxfmt/binding-android-arm64@0.48.0': optional: true - '@oxfmt/binding-darwin-arm64@0.41.0': - optional: true - '@oxfmt/binding-darwin-arm64@0.48.0': optional: true - '@oxfmt/binding-darwin-x64@0.41.0': - optional: true - '@oxfmt/binding-darwin-x64@0.48.0': optional: true - '@oxfmt/binding-freebsd-x64@0.41.0': - optional: true - '@oxfmt/binding-freebsd-x64@0.48.0': optional: true - '@oxfmt/binding-linux-arm-gnueabihf@0.41.0': - optional: true - '@oxfmt/binding-linux-arm-gnueabihf@0.48.0': optional: true - '@oxfmt/binding-linux-arm-musleabihf@0.41.0': - optional: true - '@oxfmt/binding-linux-arm-musleabihf@0.48.0': optional: true - '@oxfmt/binding-linux-arm64-gnu@0.41.0': - optional: true - '@oxfmt/binding-linux-arm64-gnu@0.48.0': optional: true - '@oxfmt/binding-linux-arm64-musl@0.41.0': - optional: true - '@oxfmt/binding-linux-arm64-musl@0.48.0': optional: true - '@oxfmt/binding-linux-ppc64-gnu@0.41.0': - optional: true - '@oxfmt/binding-linux-ppc64-gnu@0.48.0': optional: true - '@oxfmt/binding-linux-riscv64-gnu@0.41.0': - optional: true - '@oxfmt/binding-linux-riscv64-gnu@0.48.0': optional: true - '@oxfmt/binding-linux-riscv64-musl@0.41.0': - optional: true - '@oxfmt/binding-linux-riscv64-musl@0.48.0': optional: true - '@oxfmt/binding-linux-s390x-gnu@0.41.0': - optional: true - '@oxfmt/binding-linux-s390x-gnu@0.48.0': optional: true - '@oxfmt/binding-linux-x64-gnu@0.41.0': - optional: true - '@oxfmt/binding-linux-x64-gnu@0.48.0': optional: true - '@oxfmt/binding-linux-x64-musl@0.41.0': - optional: true - '@oxfmt/binding-linux-x64-musl@0.48.0': optional: true - '@oxfmt/binding-openharmony-arm64@0.41.0': - optional: true - '@oxfmt/binding-openharmony-arm64@0.48.0': optional: true - '@oxfmt/binding-win32-arm64-msvc@0.41.0': - optional: true - '@oxfmt/binding-win32-arm64-msvc@0.48.0': optional: true - '@oxfmt/binding-win32-ia32-msvc@0.41.0': - optional: true - '@oxfmt/binding-win32-ia32-msvc@0.48.0': optional: true - '@oxfmt/binding-win32-x64-msvc@0.41.0': - optional: true - '@oxfmt/binding-win32-x64-msvc@0.48.0': optional: true - '@oxlint-tsgolint/darwin-arm64@0.17.1': - optional: true - '@oxlint-tsgolint/darwin-arm64@0.22.1': optional: true - '@oxlint-tsgolint/darwin-x64@0.17.1': - optional: true - '@oxlint-tsgolint/darwin-x64@0.22.1': optional: true - '@oxlint-tsgolint/linux-arm64@0.17.1': - optional: true - '@oxlint-tsgolint/linux-arm64@0.22.1': optional: true - '@oxlint-tsgolint/linux-x64@0.17.1': - optional: true - '@oxlint-tsgolint/linux-x64@0.22.1': optional: true - '@oxlint-tsgolint/win32-arm64@0.17.1': - optional: true - '@oxlint-tsgolint/win32-arm64@0.22.1': optional: true - '@oxlint-tsgolint/win32-x64@0.17.1': - optional: true - '@oxlint-tsgolint/win32-x64@0.22.1': optional: true - '@oxlint/binding-android-arm-eabi@1.56.0': - optional: true - '@oxlint/binding-android-arm-eabi@1.63.0': optional: true - '@oxlint/binding-android-arm64@1.56.0': - optional: true - '@oxlint/binding-android-arm64@1.63.0': optional: true - '@oxlint/binding-darwin-arm64@1.56.0': - optional: true - - '@oxlint/binding-darwin-arm64@1.63.0': - optional: true - - '@oxlint/binding-darwin-x64@1.56.0': - optional: true - - '@oxlint/binding-darwin-x64@1.63.0': - optional: true - - '@oxlint/binding-freebsd-x64@1.56.0': + '@oxlint/binding-darwin-arm64@1.63.0': optional: true - '@oxlint/binding-freebsd-x64@1.63.0': + '@oxlint/binding-darwin-x64@1.63.0': optional: true - '@oxlint/binding-linux-arm-gnueabihf@1.56.0': + '@oxlint/binding-freebsd-x64@1.63.0': optional: true '@oxlint/binding-linux-arm-gnueabihf@1.63.0': optional: true - '@oxlint/binding-linux-arm-musleabihf@1.56.0': - optional: true - '@oxlint/binding-linux-arm-musleabihf@1.63.0': optional: true - '@oxlint/binding-linux-arm64-gnu@1.56.0': - optional: true - '@oxlint/binding-linux-arm64-gnu@1.63.0': optional: true - '@oxlint/binding-linux-arm64-musl@1.56.0': - optional: true - '@oxlint/binding-linux-arm64-musl@1.63.0': optional: true - '@oxlint/binding-linux-ppc64-gnu@1.56.0': - optional: true - '@oxlint/binding-linux-ppc64-gnu@1.63.0': optional: true - '@oxlint/binding-linux-riscv64-gnu@1.56.0': - optional: true - '@oxlint/binding-linux-riscv64-gnu@1.63.0': optional: true - '@oxlint/binding-linux-riscv64-musl@1.56.0': - optional: true - '@oxlint/binding-linux-riscv64-musl@1.63.0': optional: true - '@oxlint/binding-linux-s390x-gnu@1.56.0': - optional: true - '@oxlint/binding-linux-s390x-gnu@1.63.0': optional: true - '@oxlint/binding-linux-x64-gnu@1.56.0': - optional: true - '@oxlint/binding-linux-x64-gnu@1.63.0': optional: true - '@oxlint/binding-linux-x64-musl@1.56.0': - optional: true - '@oxlint/binding-linux-x64-musl@1.63.0': optional: true - '@oxlint/binding-openharmony-arm64@1.56.0': - optional: true - '@oxlint/binding-openharmony-arm64@1.63.0': optional: true - '@oxlint/binding-win32-arm64-msvc@1.56.0': - optional: true - '@oxlint/binding-win32-arm64-msvc@1.63.0': optional: true - '@oxlint/binding-win32-ia32-msvc@1.56.0': - optional: true - '@oxlint/binding-win32-ia32-msvc@1.63.0': optional: true - '@oxlint/binding-win32-x64-msvc@1.56.0': - optional: true - '@oxlint/binding-win32-x64-msvc@1.63.0': optional: true @@ -12481,24 +11680,6 @@ snapshots: - yaml optional: true - '@tsdown/css@0.21.4(jiti@2.6.1)(postcss-import@16.1.1(postcss@8.5.14))(postcss-modules@6.0.1(postcss@8.5.14))(postcss@8.5.14)(sass-embedded@1.99.0(source-map-js@1.2.1))(sass@1.99.0)(tsdown@0.21.4)(tsx@4.21.0)(yaml@2.8.2)': - dependencies: - lightningcss: 1.32.0 - postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.14)(tsx@4.21.0)(yaml@2.8.2) - rolldown: link:rolldown/packages/rolldown - tsdown: 0.21.4(@arethetypeswrong/core@0.18.2)(@tsdown/css@0.21.4)(@tsdown/exe@0.21.4)(@typescript/native-preview@7.0.0-dev.20260122.2)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(oxc-resolver@11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0))(publint@0.3.19)(typescript@6.0.2)(unplugin-unused@0.5.6) - optionalDependencies: - postcss: 8.5.14 - postcss-import: 16.1.1(postcss@8.5.14) - postcss-modules: 6.0.1(postcss@8.5.14) - sass: 1.99.0 - sass-embedded: 1.99.0(source-map-js@1.2.1) - transitivePeerDependencies: - - jiti - - tsx - - yaml - optional: true - '@tsdown/css@0.22.0(jiti@2.6.1)(postcss-import@16.1.1(postcss@8.5.14))(postcss-modules@6.0.1(postcss@8.5.14))(postcss@8.5.14)(sass-embedded@1.99.0(source-map-js@1.2.1))(sass@1.99.0)(tsdown@0.22.0)(tsx@4.21.0)(yaml@2.8.2)': dependencies: lightningcss: 1.32.0 @@ -12524,14 +11705,6 @@ snapshots: tsdown: 0.21.10(@arethetypeswrong/core@0.18.2)(@tsdown/css@0.21.10)(@tsdown/exe@0.21.10)(@typescript/native-preview@7.0.0-dev.20260122.2)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(publint@0.3.19)(typescript@6.0.2)(unplugin-unused@0.5.6) optional: true - '@tsdown/exe@0.21.4(tsdown@0.21.4)': - dependencies: - obug: 2.1.1 - semver: 7.7.4 - tinyexec: 1.1.2 - tsdown: 0.21.4(@arethetypeswrong/core@0.18.2)(@tsdown/css@0.21.4)(@tsdown/exe@0.21.4)(@typescript/native-preview@7.0.0-dev.20260122.2)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(oxc-resolver@11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0))(publint@0.3.19)(typescript@6.0.2)(unplugin-unused@0.5.6) - optional: true - '@tsdown/exe@0.22.0(tsdown@0.22.0)': dependencies: obug: 2.1.1 @@ -12673,7 +11846,8 @@ snapshots: '@types/validate-npm-package-name@4.0.2': {} - '@types/whatwg-mimetype@3.0.2': {} + '@types/whatwg-mimetype@3.0.2': + optional: true '@types/which@2.0.2': {} @@ -13015,7 +12189,7 @@ snapshots: '@vitest/mocker': 4.1.5(vite@packages+core) playwright: 1.57.0 tinyrainbow: 3.1.0 - vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5(playwright@1.57.0)(vite@packages+core)(vitest@4.1.5))(@vitest/browser-preview@4.1.5(vite@packages+core)(vitest@4.1.5))(@vitest/browser-webdriverio@4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1))(@vitest/coverage-istanbul@4.1.5(vitest@4.1.5))(@vitest/coverage-v8@4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5))(@vitest/ui@4.1.5(vitest@4.1.5))(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) + vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.10.3)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) transitivePeerDependencies: - bufferutil - msw @@ -13027,7 +12201,7 @@ snapshots: '@testing-library/dom': 10.4.1 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) '@vitest/browser': 4.1.5(vite@packages+core)(vitest@4.1.5) - vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5(playwright@1.57.0)(vite@packages+core)(vitest@4.1.5))(@vitest/browser-preview@4.1.5(vite@packages+core)(vitest@4.1.5))(@vitest/browser-webdriverio@4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1))(@vitest/coverage-istanbul@4.1.5(vitest@4.1.5))(@vitest/coverage-v8@4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5))(@vitest/ui@4.1.5(vitest@4.1.5))(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) + vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.10.3)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) transitivePeerDependencies: - bufferutil - msw @@ -13037,7 +12211,7 @@ snapshots: '@vitest/browser-webdriverio@4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1)': dependencies: '@vitest/browser': 4.1.5(vite@packages+core)(vitest@4.1.5) - vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5(playwright@1.57.0)(vite@packages+core)(vitest@4.1.5))(@vitest/browser-preview@4.1.5(vite@packages+core)(vitest@4.1.5))(@vitest/browser-webdriverio@4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1))(@vitest/coverage-istanbul@4.1.5(vitest@4.1.5))(@vitest/coverage-v8@4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5))(@vitest/ui@4.1.5(vitest@4.1.5))(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) + vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.10.3)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) webdriverio: 9.20.1 transitivePeerDependencies: - bufferutil @@ -13054,7 +12228,7 @@ snapshots: pngjs: 7.0.0 sirv: 3.0.2(patch_hash=c07c56eb72faea34341d465cde2314e89db472106ed378181e3447893af6bf95) tinyrainbow: 3.1.0 - vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5(playwright@1.57.0)(vite@packages+core)(vitest@4.1.5))(@vitest/browser-preview@4.1.5(vite@packages+core)(vitest@4.1.5))(@vitest/browser-webdriverio@4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1))(@vitest/coverage-istanbul@4.1.5(vitest@4.1.5))(@vitest/coverage-v8@4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5))(@vitest/ui@4.1.5(vitest@4.1.5))(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) + vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.10.3)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) ws: 8.20.0 transitivePeerDependencies: - bufferutil @@ -13074,9 +12248,10 @@ snapshots: magicast: 0.5.2 obug: 2.1.1 tinyrainbow: 3.1.0 - vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5(playwright@1.57.0)(vite@packages+core)(vitest@4.1.5))(@vitest/browser-preview@4.1.5(vite@packages+core)(vitest@4.1.5))(@vitest/browser-webdriverio@4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1))(@vitest/coverage-istanbul@4.1.5(vitest@4.1.5))(@vitest/coverage-v8@4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5))(@vitest/ui@4.1.5(vitest@4.1.5))(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) + vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.10.3)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) transitivePeerDependencies: - supports-color + optional: true '@vitest/coverage-v8@4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5)': dependencies: @@ -13090,9 +12265,10 @@ snapshots: obug: 2.1.1 std-env: 4.0.0 tinyrainbow: 3.1.0 - vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5(playwright@1.57.0)(vite@packages+core)(vitest@4.1.5))(@vitest/browser-preview@4.1.5(vite@packages+core)(vitest@4.1.5))(@vitest/browser-webdriverio@4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1))(@vitest/coverage-istanbul@4.1.5(vitest@4.1.5))(@vitest/coverage-v8@4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5))(@vitest/ui@4.1.5(vitest@4.1.5))(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) + vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.10.3)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) optionalDependencies: '@vitest/browser': 4.1.5(vite@packages+core)(vitest@4.1.5) + optional: true '@vitest/expect@4.1.5': dependencies: @@ -13138,7 +12314,8 @@ snapshots: sirv: 3.0.2(patch_hash=c07c56eb72faea34341d465cde2314e89db472106ed378181e3447893af6bf95) tinyglobby: 0.2.16 tinyrainbow: 3.1.0 - vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5(playwright@1.57.0)(vite@packages+core)(vitest@4.1.5))(@vitest/browser-preview@4.1.5(vite@packages+core)(vitest@4.1.5))(@vitest/browser-webdriverio@4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1))(@vitest/coverage-istanbul@4.1.5(vitest@4.1.5))(@vitest/coverage-v8@4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5))(@vitest/ui@4.1.5(vitest@4.1.5))(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) + vitest: 4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.10.3)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core) + optional: true '@vitest/utils@4.1.5': dependencies: @@ -13146,94 +12323,6 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 - '@voidzero-dev/vite-plus-core@0.1.13(@arethetypeswrong/core@0.18.2)(@tsdown/css@0.21.4)(@tsdown/exe@0.21.4)(@types/node@24.10.3)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(publint@0.3.19)(sass-embedded@1.99.0(source-map-js@1.2.1))(sass@1.99.0)(stylus@0.64.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.46.2)(tsx@4.21.0)(typescript@6.0.2)(unplugin-unused@0.5.6)(yaml@2.8.2)': - dependencies: - '@oxc-project/runtime': 0.120.0 - '@oxc-project/types': 0.120.0 - lightningcss: 1.32.0 - postcss: 8.5.14 - optionalDependencies: - '@arethetypeswrong/core': 0.18.2 - '@tsdown/css': 0.21.4(jiti@2.6.1)(postcss-import@16.1.1(postcss@8.5.14))(postcss-modules@6.0.1(postcss@8.5.14))(postcss@8.5.14)(sass-embedded@1.99.0(source-map-js@1.2.1))(sass@1.99.0)(tsdown@0.21.4)(tsx@4.21.0)(yaml@2.8.2) - '@tsdown/exe': 0.21.4(tsdown@0.21.4) - '@types/node': 24.10.3 - '@vitejs/devtools': 0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core) - esbuild: 0.27.4 - fsevents: 2.3.3 - jiti: 2.6.1 - less: 4.4.2 - publint: 0.3.19 - sass: 1.99.0 - sass-embedded: 1.99.0(source-map-js@1.2.1) - stylus: 0.64.0 - sugarss: 5.0.1(postcss@8.5.14) - terser: 5.46.2 - tsx: 4.21.0 - typescript: 6.0.2 - unplugin-unused: 0.5.6 - yaml: 2.8.2 - - '@voidzero-dev/vite-plus-darwin-arm64@0.1.13': - optional: true - - '@voidzero-dev/vite-plus-darwin-x64@0.1.13': - optional: true - - '@voidzero-dev/vite-plus-linux-arm64-gnu@0.1.13': - optional: true - - '@voidzero-dev/vite-plus-linux-x64-gnu@0.1.13': - optional: true - - '@voidzero-dev/vite-plus-test@0.1.13(@arethetypeswrong/core@0.18.2)(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@tsdown/css@0.21.4)(@tsdown/exe@0.21.4)(@types/node@24.10.3)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(esbuild@0.27.4)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.2.0)(less@4.4.2)(publint@0.3.19)(sass-embedded@1.99.0(source-map-js@1.2.1))(sass@1.99.0)(stylus@0.64.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.46.2)(tsx@4.21.0)(typescript@6.0.2)(unplugin-unused@0.5.6)(vite@packages+core)(yaml@2.8.2)': - dependencies: - '@standard-schema/spec': 1.1.0 - '@types/chai': 5.2.3 - '@voidzero-dev/vite-plus-core': 0.1.13(@arethetypeswrong/core@0.18.2)(@tsdown/css@0.21.4)(@tsdown/exe@0.21.4)(@types/node@24.10.3)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(publint@0.3.19)(sass-embedded@1.99.0(source-map-js@1.2.1))(sass@1.99.0)(stylus@0.64.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.46.2)(tsx@4.21.0)(typescript@6.0.2)(unplugin-unused@0.5.6)(yaml@2.8.2) - es-module-lexer: 1.7.0 - obug: 2.1.1 - pixelmatch: 7.1.0 - pngjs: 7.0.0 - sirv: 3.0.2(patch_hash=c07c56eb72faea34341d465cde2314e89db472106ed378181e3447893af6bf95) - std-env: 4.0.0 - tinybench: 2.9.0 - tinyexec: 1.1.2 - tinyglobby: 0.2.16 - vite: link:packages/core - ws: 8.20.0 - optionalDependencies: - '@edge-runtime/vm': 5.0.0 - '@opentelemetry/api': 1.9.0 - '@types/node': 24.10.3 - happy-dom: 20.0.10 - jsdom: 27.2.0 - transitivePeerDependencies: - - '@arethetypeswrong/core' - - '@tsdown/css' - - '@tsdown/exe' - - '@vitejs/devtools' - - bufferutil - - esbuild - - jiti - - less - - publint - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - typescript - - unplugin-unused - - utf-8-validate - - yaml - - '@voidzero-dev/vite-plus-win32-arm64-msvc@0.1.13': - optional: true - - '@voidzero-dev/vite-plus-win32-x64-msvc@0.1.13': - optional: true - '@vue-macros/common@3.1.2(vue@3.5.34(typescript@6.0.2))': dependencies: '@vue/compiler-sfc': 3.5.34 @@ -13525,6 +12614,7 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 estree-walker: 3.0.3 js-tokens: 10.0.0 + optional: true ast-walker-scope@0.8.3: dependencies: @@ -13613,6 +12703,7 @@ snapshots: bidi-js@1.0.3: dependencies: require-from-string: 2.0.2 + optional: true binary-extensions@2.3.0: {} @@ -13966,6 +13057,7 @@ snapshots: dependencies: mdn-data: 2.12.2 source-map-js: 1.2.1 + optional: true css-value@0.0.1: {} @@ -13978,6 +13070,7 @@ snapshots: '@asamuzakjp/css-color': 4.1.0 '@csstools/css-syntax-patches-for-csstree': 1.0.17 css-tree: 3.1.0 + optional: true csstype@3.2.3: {} @@ -13995,6 +13088,7 @@ snapshots: dependencies: whatwg-mimetype: 4.0.0 whatwg-url: 15.1.0 + optional: true debug@2.6.9: dependencies: @@ -14010,7 +13104,8 @@ snapshots: decamelize@6.0.1: {} - decimal.js@10.6.0: {} + decimal.js@10.6.0: + optional: true decircular@0.1.1: {} @@ -14740,6 +13835,7 @@ snapshots: '@types/node': 20.19.25 '@types/whatwg-mimetype': 3.0.2 whatwg-mimetype: 3.0.0 + optional: true has-flag@3.0.0: {} @@ -14775,8 +13871,10 @@ snapshots: html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 + optional: true - html-escaper@2.0.2: {} + html-escaper@2.0.2: + optional: true htmlfy@0.8.1: {} @@ -14854,9 +13952,6 @@ snapshots: import-meta-resolve@4.2.0: {} - import-without-cache@0.2.5: - optional: true - import-without-cache@0.3.3: {} import-without-cache@0.4.0: {} @@ -14917,7 +14012,8 @@ snapshots: is-plain-obj@4.1.0: {} - is-potential-custom-element-name@1.0.1: {} + is-potential-custom-element-name@1.0.1: + optional: true is-reference@1.2.1: dependencies: @@ -14957,18 +14053,21 @@ snapshots: isexe@3.1.1: {} - istanbul-lib-coverage@3.2.2: {} + istanbul-lib-coverage@3.2.2: + optional: true istanbul-lib-report@3.0.1: dependencies: istanbul-lib-coverage: 3.2.2 make-dir: 4.0.0 supports-color: 7.2.0 + optional: true istanbul-reports@3.2.0: dependencies: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 + optional: true jackspeak@3.4.3: dependencies: @@ -14978,7 +14077,8 @@ snapshots: jiti@2.6.1: {} - js-tokens@10.0.0: {} + js-tokens@10.0.0: + optional: true js-tokens@4.0.0: {} @@ -15021,6 +14121,7 @@ snapshots: - bufferutil - supports-color - utf-8-validate + optional: true jsesc@0.5.0: {} @@ -15269,6 +14370,7 @@ snapshots: '@babel/parser': 7.29.3 '@babel/types': 7.29.0 source-map-js: 1.2.1 + optional: true make-dir@2.1.0: dependencies: @@ -15279,13 +14381,15 @@ snapshots: make-dir@4.0.0: dependencies: semver: 7.7.4 + optional: true matcher-collection@2.0.1: dependencies: '@types/minimatch': 3.0.5 minimatch: 3.1.5 - mdn-data@2.12.2: {} + mdn-data@2.12.2: + optional: true meow@13.2.0: {} @@ -15643,30 +14747,6 @@ snapshots: '@oxc-transform/binding-win32-ia32-msvc': 0.129.0 '@oxc-transform/binding-win32-x64-msvc': 0.129.0 - oxfmt@0.41.0: - dependencies: - tinypool: 2.1.0 - optionalDependencies: - '@oxfmt/binding-android-arm-eabi': 0.41.0 - '@oxfmt/binding-android-arm64': 0.41.0 - '@oxfmt/binding-darwin-arm64': 0.41.0 - '@oxfmt/binding-darwin-x64': 0.41.0 - '@oxfmt/binding-freebsd-x64': 0.41.0 - '@oxfmt/binding-linux-arm-gnueabihf': 0.41.0 - '@oxfmt/binding-linux-arm-musleabihf': 0.41.0 - '@oxfmt/binding-linux-arm64-gnu': 0.41.0 - '@oxfmt/binding-linux-arm64-musl': 0.41.0 - '@oxfmt/binding-linux-ppc64-gnu': 0.41.0 - '@oxfmt/binding-linux-riscv64-gnu': 0.41.0 - '@oxfmt/binding-linux-riscv64-musl': 0.41.0 - '@oxfmt/binding-linux-s390x-gnu': 0.41.0 - '@oxfmt/binding-linux-x64-gnu': 0.41.0 - '@oxfmt/binding-linux-x64-musl': 0.41.0 - '@oxfmt/binding-openharmony-arm64': 0.41.0 - '@oxfmt/binding-win32-arm64-msvc': 0.41.0 - '@oxfmt/binding-win32-ia32-msvc': 0.41.0 - '@oxfmt/binding-win32-x64-msvc': 0.41.0 - oxfmt@0.48.0: dependencies: tinypool: 2.1.0 @@ -15691,15 +14771,6 @@ snapshots: '@oxfmt/binding-win32-ia32-msvc': 0.48.0 '@oxfmt/binding-win32-x64-msvc': 0.48.0 - oxlint-tsgolint@0.17.1: - optionalDependencies: - '@oxlint-tsgolint/darwin-arm64': 0.17.1 - '@oxlint-tsgolint/darwin-x64': 0.17.1 - '@oxlint-tsgolint/linux-arm64': 0.17.1 - '@oxlint-tsgolint/linux-x64': 0.17.1 - '@oxlint-tsgolint/win32-arm64': 0.17.1 - '@oxlint-tsgolint/win32-x64': 0.17.1 - oxlint-tsgolint@0.22.1: optionalDependencies: '@oxlint-tsgolint/darwin-arm64': 0.22.1 @@ -15709,29 +14780,6 @@ snapshots: '@oxlint-tsgolint/win32-arm64': 0.22.1 '@oxlint-tsgolint/win32-x64': 0.22.1 - oxlint@1.56.0(oxlint-tsgolint@0.17.1): - optionalDependencies: - '@oxlint/binding-android-arm-eabi': 1.56.0 - '@oxlint/binding-android-arm64': 1.56.0 - '@oxlint/binding-darwin-arm64': 1.56.0 - '@oxlint/binding-darwin-x64': 1.56.0 - '@oxlint/binding-freebsd-x64': 1.56.0 - '@oxlint/binding-linux-arm-gnueabihf': 1.56.0 - '@oxlint/binding-linux-arm-musleabihf': 1.56.0 - '@oxlint/binding-linux-arm64-gnu': 1.56.0 - '@oxlint/binding-linux-arm64-musl': 1.56.0 - '@oxlint/binding-linux-ppc64-gnu': 1.56.0 - '@oxlint/binding-linux-riscv64-gnu': 1.56.0 - '@oxlint/binding-linux-riscv64-musl': 1.56.0 - '@oxlint/binding-linux-s390x-gnu': 1.56.0 - '@oxlint/binding-linux-x64-gnu': 1.56.0 - '@oxlint/binding-linux-x64-musl': 1.56.0 - '@oxlint/binding-openharmony-arm64': 1.56.0 - '@oxlint/binding-win32-arm64-msvc': 1.56.0 - '@oxlint/binding-win32-ia32-msvc': 1.56.0 - '@oxlint/binding-win32-x64-msvc': 1.56.0 - oxlint-tsgolint: 0.17.1 - oxlint@1.63.0(oxlint-tsgolint@0.22.1): optionalDependencies: '@oxlint/binding-android-arm-eabi': 1.63.0 @@ -15885,10 +14933,6 @@ snapshots: pirates@4.0.7: {} - pixelmatch@7.1.0: - dependencies: - pngjs: 7.0.0 - pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -16179,7 +15223,8 @@ snapshots: require-directory@2.1.1: {} - require-from-string@2.0.2: {} + require-from-string@2.0.2: + optional: true resolve-from@4.0.0: {} @@ -16210,25 +15255,6 @@ snapshots: rgb2hex@0.2.5: {} - rolldown-plugin-dts@0.22.5(@typescript/native-preview@7.0.0-dev.20260122.2)(oxc-resolver@11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0))(rolldown@rolldown+packages+rolldown)(typescript@6.0.2): - dependencies: - '@babel/generator': 8.0.0-rc.2 - '@babel/helper-validator-identifier': 8.0.0-rc.2 - '@babel/parser': 8.0.0-rc.2 - '@babel/types': 8.0.0-rc.2 - ast-kit: 3.0.0-beta.1 - birpc: 4.0.0 - dts-resolver: 2.1.3(oxc-resolver@11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)) - get-tsconfig: 4.13.7 - obug: 2.1.1 - rolldown: link:rolldown/packages/rolldown - optionalDependencies: - '@typescript/native-preview': 7.0.0-dev.20260122.2 - typescript: 6.0.2 - transitivePeerDependencies: - - oxc-resolver - optional: true - rolldown-plugin-dts@0.23.2(@typescript/native-preview@7.0.0-dev.20260122.2)(oxc-resolver@11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0))(rolldown@rolldown+packages+rolldown)(typescript@6.0.2): dependencies: '@babel/generator': 8.0.0-rc.3 @@ -16454,6 +15480,7 @@ snapshots: saxes@6.0.0: dependencies: xmlchars: 2.2.0 + optional: true scheduler@0.27.0: {} @@ -16726,7 +15753,8 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - symbol-tree@3.2.4: {} + symbol-tree@3.2.4: + optional: true sync-child-process@1.0.2: dependencies: @@ -16789,11 +15817,13 @@ snapshots: tinyrainbow@3.1.0: {} - tldts-core@7.0.19: {} + tldts-core@7.0.19: + optional: true tldts@7.0.19: dependencies: tldts-core: 7.0.19 + optional: true to-regex-range@5.0.1: dependencies: @@ -16808,10 +15838,12 @@ snapshots: tough-cookie@6.0.0: dependencies: tldts: 7.0.19 + optional: true tr46@6.0.0: dependencies: punycode: 2.3.1 + optional: true tree-kill@1.2.2: {} @@ -16857,40 +15889,6 @@ snapshots: - synckit - vue-tsc - tsdown@0.21.4(@arethetypeswrong/core@0.18.2)(@tsdown/css@0.21.4)(@tsdown/exe@0.21.4)(@typescript/native-preview@7.0.0-dev.20260122.2)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(oxc-resolver@11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0))(publint@0.3.19)(typescript@6.0.2)(unplugin-unused@0.5.6): - dependencies: - ansis: 4.2.0 - cac: 7.0.0 - defu: 6.1.7 - empathic: 2.0.0 - hookable: 6.1.1 - import-without-cache: 0.2.5 - obug: 2.1.1 - picomatch: 4.0.4 - rolldown: link:rolldown/packages/rolldown - rolldown-plugin-dts: 0.22.5(@typescript/native-preview@7.0.0-dev.20260122.2)(oxc-resolver@11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0))(rolldown@rolldown+packages+rolldown)(typescript@6.0.2) - semver: 7.7.4 - tinyexec: 1.1.2 - tinyglobby: 0.2.16 - tree-kill: 1.2.2 - unconfig-core: 7.5.0 - unrun: 0.2.37 - optionalDependencies: - '@arethetypeswrong/core': 0.18.2 - '@tsdown/css': 0.21.4(jiti@2.6.1)(postcss-import@16.1.1(postcss@8.5.14))(postcss-modules@6.0.1(postcss@8.5.14))(postcss@8.5.14)(sass-embedded@1.99.0(source-map-js@1.2.1))(sass@1.99.0)(tsdown@0.21.4)(tsx@4.21.0)(yaml@2.8.2) - '@tsdown/exe': 0.21.4(tsdown@0.21.4) - '@vitejs/devtools': 0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core) - publint: 0.3.19 - typescript: 6.0.2 - unplugin-unused: 0.5.6 - transitivePeerDependencies: - - '@ts-macro/tsc' - - '@typescript/native-preview' - - oxc-resolver - - synckit - - vue-tsc - optional: true - tsdown@0.22.0(@arethetypeswrong/core@0.18.2)(@tsdown/css@0.22.0)(@tsdown/exe@0.22.0)(@typescript/native-preview@7.0.0-dev.20260122.2)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(oxc-resolver@11.19.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0))(publint@0.3.19)(tsx@4.21.0)(typescript@6.0.2)(unplugin-unused@0.5.6)(unrun@0.2.37): dependencies: ansis: 4.2.0 @@ -17129,53 +16127,44 @@ snapshots: vary@1.1.2: {} - vite-plus@0.1.13(@arethetypeswrong/core@0.18.2)(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@tsdown/css@0.21.4)(@tsdown/exe@0.21.4)(@types/node@24.10.3)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(esbuild@0.27.4)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.2.0)(less@4.4.2)(publint@0.3.19)(sass-embedded@1.99.0(source-map-js@1.2.1))(sass@1.99.0)(stylus@0.64.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.46.2)(tsx@4.21.0)(typescript@6.0.2)(unplugin-unused@0.5.6)(vite@packages+core)(yaml@2.8.2): + vitest@4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.10.3)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core): dependencies: - '@oxc-project/types': 0.120.0 - '@voidzero-dev/vite-plus-core': 0.1.13(@arethetypeswrong/core@0.18.2)(@tsdown/css@0.21.4)(@tsdown/exe@0.21.4)(@types/node@24.10.3)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(esbuild@0.27.4)(jiti@2.6.1)(less@4.4.2)(publint@0.3.19)(sass-embedded@1.99.0(source-map-js@1.2.1))(sass@1.99.0)(stylus@0.64.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.46.2)(tsx@4.21.0)(typescript@6.0.2)(unplugin-unused@0.5.6)(yaml@2.8.2) - '@voidzero-dev/vite-plus-test': 0.1.13(@arethetypeswrong/core@0.18.2)(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@tsdown/css@0.21.4)(@tsdown/exe@0.21.4)(@types/node@24.10.3)(@vitejs/devtools@0.1.21(@pnpm/logger@1001.0.1)(typescript@6.0.2)(vite@packages+core))(esbuild@0.27.4)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.2.0)(less@4.4.2)(publint@0.3.19)(sass-embedded@1.99.0(source-map-js@1.2.1))(sass@1.99.0)(stylus@0.64.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.46.2)(tsx@4.21.0)(typescript@6.0.2)(unplugin-unused@0.5.6)(vite@packages+core)(yaml@2.8.2) - cac: 7.0.0 - cross-spawn: 7.0.6 - oxfmt: 0.41.0 - oxlint: 1.56.0(oxlint-tsgolint@0.17.1) - oxlint-tsgolint: 0.17.1 - picocolors: 1.1.1 + '@vitest/expect': 4.1.5 + '@vitest/mocker': 4.1.5(vite@packages+core) + '@vitest/pretty-format': 4.1.5 + '@vitest/runner': 4.1.5 + '@vitest/snapshot': 4.1.5 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 + es-module-lexer: 2.0.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.0.0 + tinybench: 2.9.0 + tinyexec: 1.1.2 + tinyglobby: 0.2.16 + tinyrainbow: 3.1.0 + vite: link:packages/core + why-is-node-running: 2.3.0 optionalDependencies: - '@voidzero-dev/vite-plus-darwin-arm64': 0.1.13 - '@voidzero-dev/vite-plus-darwin-x64': 0.1.13 - '@voidzero-dev/vite-plus-linux-arm64-gnu': 0.1.13 - '@voidzero-dev/vite-plus-linux-x64-gnu': 0.1.13 - '@voidzero-dev/vite-plus-win32-arm64-msvc': 0.1.13 - '@voidzero-dev/vite-plus-win32-x64-msvc': 0.1.13 + '@edge-runtime/vm': 5.0.0 + '@opentelemetry/api': 1.9.0 + '@types/node': 24.10.3 + '@vitest/browser-playwright': 4.1.5(playwright@1.57.0)(vite@packages+core)(vitest@4.1.5) + '@vitest/browser-preview': 4.1.5(vite@packages+core)(vitest@4.1.5) + '@vitest/browser-webdriverio': 4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1) + '@vitest/coverage-istanbul': 4.1.5(vitest@4.1.5) + '@vitest/coverage-v8': 4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5) + '@vitest/ui': 4.1.5(vitest@4.1.5) + happy-dom: 20.0.10 + jsdom: 27.2.0 transitivePeerDependencies: - - '@arethetypeswrong/core' - - '@edge-runtime/vm' - - '@opentelemetry/api' - - '@tsdown/css' - - '@tsdown/exe' - - '@types/node' - - '@vitejs/devtools' - - '@vitest/ui' - - bufferutil - - esbuild - - happy-dom - - jiti - - jsdom - - less - - publint - - sass - - sass-embedded - - stylus - - sugarss - - terser - - tsx - - typescript - - unplugin-unused - - utf-8-validate - - vite - - yaml + - msw - vitest@4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5(playwright@1.57.0)(vite@packages+core)(vitest@4.1.5))(@vitest/browser-preview@4.1.5(vite@packages+core)(vitest@4.1.5))(@vitest/browser-webdriverio@4.1.5(vite@packages+core)(vitest@4.1.5)(webdriverio@9.20.1))(@vitest/coverage-istanbul@4.1.5(vitest@4.1.5))(@vitest/coverage-v8@4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5))(@vitest/ui@4.1.5(vitest@4.1.5))(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core): + vitest@4.1.5(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.5)(@vitest/browser-preview@4.1.5)(@vitest/browser-webdriverio@4.1.5)(@vitest/coverage-istanbul@4.1.5)(@vitest/coverage-v8@4.1.5)(@vitest/ui@4.1.5)(happy-dom@20.0.10)(jsdom@27.2.0)(vite@packages+core): dependencies: '@vitest/expect': 4.1.5 '@vitest/mocker': 4.1.5(vite@packages+core) @@ -17252,6 +16241,7 @@ snapshots: w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 + optional: true wait-port@1.1.0: dependencies: @@ -17328,7 +16318,8 @@ snapshots: - supports-color - utf-8-validate - webidl-conversions@8.0.0: {} + webidl-conversions@8.0.0: + optional: true webpack-virtual-modules@0.6.2: {} @@ -17336,7 +16327,8 @@ snapshots: dependencies: iconv-lite: 0.6.3 - whatwg-mimetype@3.0.0: {} + whatwg-mimetype@3.0.0: + optional: true whatwg-mimetype@4.0.0: {} @@ -17344,6 +16336,7 @@ snapshots: dependencies: tr46: 6.0.0 webidl-conversions: 8.0.0 + optional: true which@2.0.2: dependencies: @@ -17411,9 +16404,11 @@ snapshots: is-wsl: 3.1.0 powershell-utils: 0.1.0 - xml-name-validator@5.0.0: {} + xml-name-validator@5.0.0: + optional: true - xmlchars@2.2.0: {} + xmlchars@2.2.0: + optional: true y18n@5.0.8: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 026a502962..cbb8ec5f3d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -39,8 +39,10 @@ catalog: '@types/ws': ^8.18.0 '@typescript/native-preview': 7.0.0-dev.20260122.2 '@vitejs/plugin-react': ^5.1.2 - '@vitest/browser': ^4.0.9 - '@vitest/browser-playwright': ^4.0.9 + '@vitest/browser': 4.1.5 + '@vitest/browser-playwright': 4.1.5 + '@vitest/browser-preview': 4.1.5 + '@vitest/browser-webdriverio': 4.1.5 '@voidzero-dev/vitepress-theme': 4.8.3 '@vueuse/core': ^14.0.0 '@yarnpkg/fslib': ^3.1.3 @@ -115,7 +117,7 @@ catalog: vitepress-plugin-group-icons: ^1.7.1 vitepress-plugin-llms: ^1.1.0 vitepress-plugin-og: ^0.0.5 - vitest: ^4.0.15 + vitest: 4.1.5 vue: ^3.5.21 web-tree-sitter: ^0.26.0 ws: ^8.18.1 @@ -168,8 +170,7 @@ overrides: '@rolldown/pluginutils': workspace:@rolldown/pluginutils@* rolldown: workspace:rolldown@* vite: workspace:@voidzero-dev/vite-plus-core@* - vitest: workspace:@voidzero-dev/vite-plus-test@* - vitest-dev: npm:vitest@^4.1.5 + vite-plus: workspace:vite-plus@* packageExtensions: sass-embedded: peerDependencies: diff --git a/rfcs/cli-output-polish.md b/rfcs/cli-output-polish.md index c3f4010d8b..97427add66 100644 --- a/rfcs/cli-output-polish.md +++ b/rfcs/cli-output-polish.md @@ -298,7 +298,9 @@ The `vite_install` crate also has `Warning:` and `Note:` messages across multipl ### Phase 3: Rebrand vitest Output -Vitest is bundled (not cloned source) via `@voidzero-dev/vite-plus-test`. Its build script (`packages/test/build.ts`) copies and rewrites vitest's dist files. We patch the bundled cac chunk during the build to rebrand CLI output. +> **Note:** This phase has been reverted. The `@voidzero-dev/vite-plus-test` bundled wrapper was removed in favor of consuming upstream `vitest` directly, since the `vite` → `@voidzero-dev/vite-plus-core` package manager override already handles the dependency redirection. Vitest output is no longer rebranded. + +Historical context (no longer applies): Vitest was bundled (not cloned source) via `@voidzero-dev/vite-plus-test`. Its build script (`packages/test/build.ts`) copied and rewrote vitest's dist files. We patched the bundled cac chunk during the build to rebrand CLI output. #### 3.1 Approach: Build-time patching of bundled cac chunk diff --git a/rfcs/migration-command.md b/rfcs/migration-command.md index aa2509dd5c..47ab4803c6 100644 --- a/rfcs/migration-command.md +++ b/rfcs/migration-command.md @@ -203,12 +203,10 @@ Wrote agent instructions to AGENTS.md }, "devDependencies": { "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest", "@vitejs/plugin-react": "^4.2.0" }, "overrides": { - "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest" + "vite": "npm:@voidzero-dev/vite-plus-core@latest" } } ``` @@ -223,7 +221,6 @@ Wrote agent instructions to AGENTS.md }, "devDependencies": { "vite": "catalog:", - "vitest": "catalog:", "@vitejs/plugin-react": "^4.2.0", "vite-plus": "catalog:" }, @@ -236,15 +233,12 @@ Wrote agent instructions to AGENTS.md ```yaml catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' vitest: '*' @@ -259,16 +253,14 @@ Projects that already have a `pnpm` field in `package.json` (e.g., with `overrid "name": "my-package", "devDependencies": { "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest", "vite-plus": "latest" }, "pnpm": { "overrides": { - "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest" + "vite": "npm:@voidzero-dev/vite-plus-core@latest" }, "peerDependencyRules": { - "allowAny": ["vite", "vitest"], + "allowAny": ["vite"], "allowedVersions": { "vite": "*", "vitest": "*" } } } @@ -282,13 +274,8 @@ Projects that already have a `pnpm` field in `package.json` (e.g., with `overrid - For pnpm with existing `pnpm` config in `package.json`, the existing location is respected - rewrite `import from 'vite'` to `import from 'vite-plus'` - rewrite `import from 'vite/{name}'` to `import from 'vite-plus/{name}'`, e.g.: `import from 'vite/module-runner'` to `import from 'vite-plus/module-runner'` -- rewrite `import from 'vitest'` to `import from 'vite-plus/test'` - rewrite `import from 'vitest/config'` to `import from 'vite-plus'` -- rewrite `import from 'vitest/{name}'` to `import from 'vite-plus/test/{name}'`, e.g.: `import from 'vitest/node'` to `import from 'vite-plus/test/node'` -- rewrite `import from '@vitest/browser'` to `import from 'vite-plus/test/browser'` -- rewrite `import from '@vitest/browser/{name}'` to `import from 'vite-plus/test/browser/{name}'`, e.g.: `import from '@vitest/browser/context'` to `import from 'vite-plus/test/browser/context'` -- rewrite `import from '@vitest/browser-playwright'` to `import from 'vite-plus/test/browser-playwright'` -- rewrite `import from '@vitest/browser-playwright/{name}'` to `import from 'vite-plus/test/browser-playwright/{name}'` +- bare `vitest`, other `vitest/{name}` subpaths, and all `@vitest/browser*` imports are intentionally **not** rewritten — vite-plus consumes upstream `vitest@4.x` directly (via overrides on `vite`), Vitest's mock hoister requires the literal string `'vitest'`, and the browser/provider subpaths are not re-exported by vite-plus **Note**: For Yarn, use `resolutions` instead of `overrides`. @@ -503,15 +490,12 @@ For monorepo projects and standalone projects without existing `pnpm` config in ```yaml catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest vite-plus: latest overrides: vite: 'catalog:' - vitest: 'catalog:' peerDependencyRules: allowAny: - vite - - vitest allowedVersions: vite: '*' vitest: '*' @@ -524,12 +508,10 @@ peerDependencyRules: ```json { "devDependencies": { - "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest" + "vite": "npm:@voidzero-dev/vite-plus-core@latest" }, "overrides": { - "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "npm:@voidzero-dev/vite-plus-test@latest" + "vite": "npm:@voidzero-dev/vite-plus-core@latest" } } ``` @@ -541,7 +523,6 @@ peerDependencyRules: ```yaml catalog: vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: npm:@voidzero-dev/vite-plus-test@latest ``` `package.json` @@ -549,8 +530,7 @@ catalog: ```json { "resolutions": { - "vite": "catalog:", - "vitest": "catalog:" + "vite": "catalog:" } } ``` diff --git a/vite.config.ts b/vite.config.ts index 73d6ccca86..e7218a9b23 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -70,12 +70,6 @@ export default defineConfig({ 'packages/cli/snap-tests/fmt-ignore-patterns/src/ignored', 'packages/cli/snap-tests-global/migration-lint-staged-ts-config', 'ecosystem-ci/*/**', - 'packages/test/**.cjs', - 'packages/test/**.cts', - 'packages/test/**.d.mjs', - 'packages/test/**.d.ts', - 'packages/test/**.mjs', - 'packages/test/browser/', 'packages/cli/src/run-config.ts', 'vite', 'rolldown', @@ -111,7 +105,6 @@ export default defineConfig({ 'vp run rolldown#build-node', 'vp run vite#build-types', 'vp run @voidzero-dev/vite-plus-core#build', - 'vp run @voidzero-dev/vite-plus-test#build', 'vp run vite-plus#build', ].join(' && '), }, From 6be5e863e446ace54a5ce1b8d26385547f0acd97 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 15 May 2026 19:01:06 +0800 Subject: [PATCH 02/37] fix(migration): re-pin vite-plus in force-override mode, fix lint/format/typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #1588 CI failures: - Force-override mode (VP_FORCE_MIGRATE=1, set by test-vp-create.yml and ecosystem-ci) now re-pins any pre-existing vite-plus range to the local tgz path in monorepo workspace packages. Without this, pnpm reads the published vite-plus@0.1.21 metadata to resolve transitive deps including @voidzero-dev/vite-plus-test@0.1.21, which shadowed upstream vitest@4.1.5 at runtime and broke vp create monorepo tests. - typos CI: rename yarn-PnP to yarn Plug'n'Play (Pn→On false positive). - vp check: format packages/cli/build.ts shim-generation block. - Rename __dirname in install-failure-guard.spec.ts to satisfy eslint(no-underscore-dangle). --- packages/cli/build.ts | 5 +++- .../__tests__/install-failure-guard.spec.ts | 4 ++-- packages/cli/src/migration/migrator.ts | 23 ++++++++++++++++--- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/cli/build.ts b/packages/cli/build.ts index 5041728ca2..9248371fc8 100644 --- a/packages/cli/build.ts +++ b/packages/cli/build.ts @@ -367,7 +367,10 @@ async function syncTestPackageExports() { // ./test/browser/providers/ → e.g. ./test/browser/providers/playwright const pkgShortName = pkg.startsWith('@vitest/') ? pkg.slice('@vitest/'.length) : pkg; const surfaces = [ - { cliPath: `./test/${pkgShortName}${providerSubPath}`, baseName: `${pkgShortName}${providerSubPath}` }, + { + cliPath: `./test/${pkgShortName}${providerSubPath}`, + baseName: `${pkgShortName}${providerSubPath}`, + }, { cliPath: `./test/browser/providers/${short}${providerSubPath}`, baseName: `browser/providers/${short}${providerSubPath}`, diff --git a/packages/cli/src/migration/__tests__/install-failure-guard.spec.ts b/packages/cli/src/migration/__tests__/install-failure-guard.spec.ts index 874ee16e73..6304c1f2fa 100644 --- a/packages/cli/src/migration/__tests__/install-failure-guard.spec.ts +++ b/packages/cli/src/migration/__tests__/install-failure-guard.spec.ts @@ -4,8 +4,8 @@ import { fileURLToPath } from 'node:url'; import { describe, expect, it } from 'vitest'; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const binPath = path.resolve(__dirname, '..', 'bin.ts'); +const here = path.dirname(fileURLToPath(import.meta.url)); +const binPath = path.resolve(here, '..', 'bin.ts'); /** * `runViteInstall` returns `{ status: 'failed', exitCode }` (it does not throw) diff --git a/packages/cli/src/migration/migrator.ts b/packages/cli/src/migration/migrator.ts index 1b8bb84e76..030f91028a 100644 --- a/packages/cli/src/migration/migrator.ts +++ b/packages/cli/src/migration/migrator.ts @@ -130,7 +130,9 @@ function isLegacyWrapperSpec(value: string | undefined): boolean { * is dropped entirely. Returns true iff any entry was changed. */ function pruneLegacyWrapperAliases(record: Record | undefined): boolean { - if (!record) return false; + if (!record) { + return false; + } let mutated = false; for (const key of Object.keys(record)) { if (isLegacyWrapperSpec(record[key])) { @@ -1482,7 +1484,9 @@ function getYamlMapScalarStringValue(map: unknown, key: string): string | undefi } function pruneYamlMapLegacyWrapperAliases(map: unknown): void { - if (!(map instanceof YAMLMap)) return; + if (!(map instanceof YAMLMap)) { + return; + } const stale: Array<{ key: Scalar; fallback: string | undefined }> = []; for (const item of map.items) { const value = item.value instanceof Scalar ? item.value.value : undefined; @@ -1840,6 +1844,19 @@ export function rewritePackageJson( } } } + // Force-override mode (ecosystem CI / `vp create` E2E) must re-pin any + // pre-existing `vite-plus` range to the local tgz. Otherwise pnpm reads the + // published vite-plus metadata for transitive dep resolution (e.g. + // `@voidzero-dev/vite-plus-test`) even though the override replaces the + // vite-plus package itself, dragging the stale wrapper into node_modules. + if (isForceOverrideMode()) { + for (const { dependencies } of dependencyGroups) { + if (dependencies?.[VITE_PLUS_NAME]) { + dependencies[VITE_PLUS_NAME] = VITE_PLUS_VERSION; + needVitePlus = true; + } + } + } // remove packages that are replaced with vite-plus for (const name of REMOVE_PACKAGES) { let wasRemoved = false; @@ -1894,7 +1911,7 @@ export function rewritePackageJson( // Add vitest to devDependencies when a remaining dependency likely // peer-depends on vitest (e.g., vitest-browser-svelte). Vite-plus already // bundles upstream vitest 4.1.5 as a direct dep, so the runtime resolution - // works without this — but strict pnpm / yarn-PnP refuse to expose a + // works without this — but strict pnpm / yarn Plug'n'Play refuse to expose a // transitive `vitest` to satisfy a peer dep declared by a different // direct dep. Adding `vitest` to the user's devDependencies pins the // peer-dep target to the same upstream version vite-plus ships with. From b5a78e0e3c72aaf14a56710406cc1f5115118684 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 15 May 2026 19:25:09 +0800 Subject: [PATCH 03/37] fix(migration): pass --no-frozen-lockfile to pnpm/yarn reinstall after migration The migration step intentionally rewrites overrides/catalogs/deps so the existing lockfile is guaranteed to be stale. pnpm and yarn default to frozen-lockfile mode under CI, so they refuse the reinstall with ERR_PNPM_LOCKFILE_CONFIG_MISMATCH and the new handleInstallResult enforcement propagates that failure as a non-zero exit. Add --no-frozen-lockfile alongside the existing --force for npm/bun, applied to both the post-migration reinstall and the ESLint/Prettier early-return reinstall. --- packages/cli/src/migration/bin.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/migration/bin.ts b/packages/cli/src/migration/bin.ts index 55d0dd8618..d487468c89 100644 --- a/packages/cli/src/migration/bin.ts +++ b/packages/cli/src/migration/bin.ts @@ -798,12 +798,14 @@ async function executeMigrationPlan( } // 12. Reinstall after migration - // npm needs --force to re-resolve packages with newly added overrides, - // otherwise the stale lockfile prevents override resolution. + // The migration intentionally rewrites overrides/catalogs/deps, so the + // existing lockfile is guaranteed to be stale. Tell each package manager to + // re-resolve instead of refusing the install (pnpm/yarn default to + // frozen-lockfile under CI, npm/bun need an explicit --force). const installArgs = plan.packageManager === PackageManager.npm || plan.packageManager === PackageManager.bun ? ['--force'] - : undefined; + : ['--no-frozen-lockfile']; updateMigrationProgress('Installing dependencies'); const finalInstallSummary = await runViteInstall( workspaceInfo.rootDir, @@ -926,10 +928,17 @@ async function main() { ); resolvedVersion = resolved.version; } + // ESLint/Prettier migration touched package.json; the lockfile is now + // stale, so disable frozen-lockfile mode (pnpm/yarn) or --force (npm/bun). + const eslintPrettierInstallArgs = + workspaceInfoOptional.packageManager === PackageManager.npm || + workspaceInfoOptional.packageManager === PackageManager.bun + ? ['--force'] + : ['--no-frozen-lockfile']; const installSummary = await runViteInstall( workspaceInfoOptional.rootDir, options.interactive, - undefined, + eslintPrettierInstallArgs, { silent: true, packageManager: workspaceInfoOptional.packageManager, From 4313ac2ffd6e56c9883b03d277102014131b2958 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 15 May 2026 20:37:56 +0800 Subject: [PATCH 04/37] fix(migration): preserve vitest declare-module, route browser-provider types through vite-plus, prune monorepo aliases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three independent fixes for E2E failures introduced by the vite-plus-test → upstream-vitest refactor: 1. Stop rewriting `declare module 'vitest'` (and subpaths/@vitest variants). The `vite-plus/test*` shims re-export upstream `vitest*`, so the type identity is upstream. Augmenting `'vite-plus/test'` only augments the shim and never merges into the upstream types the user actually sees through `import { expect } from 'vite-plus/test'`. Import rewrites stay; declare-module rewrites are dropped. 2. Inline-copy upstream `@vitest/browser-*` d.ts content into the test shims and rewrite `vitest/node`/`vitest/browser`/`@vitest/browser*` bare specifiers to relative paths inside the `dist/test/` tree. Without this, pnpm splits `@vitest/browser-playwright` and `vitest` across different peer-dep edges, creating two `BrowserProvider` type identities — and `provider: playwright()` fails the user's vite.config typecheck. 3. Add the same `pruneLegacyWrapperAliases` calls to `rewriteRootWorkspacePackageJson` that `rewriteStandaloneProject` already had. Monorepo migrations were leaving stale `npm:@voidzero-dev/vite-plus-test@*` aliases in root resolutions / overrides / pnpm.overrides, causing pnpm to install the deleted wrapper. Co-Authored-By: Claude Opus 4.7 --- crates/vite_migration/src/import_rewriter.rs | 249 +++++-------------- packages/cli/build.ts | 182 ++++++++++++-- packages/cli/src/migration/migrator.ts | 5 + 3 files changed, 224 insertions(+), 212 deletions(-) diff --git a/crates/vite_migration/src/import_rewriter.rs b/crates/vite_migration/src/import_rewriter.rs index 175ef58491..23d68b38bd 100644 --- a/crates/vite_migration/src/import_rewriter.rs +++ b/crates/vite_migration/src/import_rewriter.rs @@ -85,7 +85,7 @@ transform: fix: $NEW_IMPORT "#; -/// ast-grep rules for rewriting vitest imports and declare module statements +/// ast-grep rules for rewriting vitest imports. /// /// This rewrites: /// - `import { ... } from 'vitest'` → `import { ... } from 'vite-plus/test'` @@ -99,17 +99,15 @@ fix: $NEW_IMPORT /// - `import { ... } from '@vitest/browser-preview/{name}'` → `import { ... } from 'vite-plus/test/browser-preview/{name}'` /// - `import { ... } from '@vitest/browser-webdriverio'` → `import { ... } from 'vite-plus/test/browser-webdriverio'` /// - `import { ... } from '@vitest/browser-webdriverio/{name}'` → `import { ... } from 'vite-plus/test/browser-webdriverio/{name}'` -/// - `declare module 'vitest' { ... }` → `declare module 'vite-plus/test' { ... }` -/// - `declare module 'vitest/config' { ... }` → `declare module 'vite-plus' { ... }` -/// - `declare module 'vitest/{name}' { ... }` → `declare module 'vite-plus/test/{name}' { ... }` -/// - `declare module '@vitest/browser' { ... }` → `declare module 'vite-plus/test/browser' { ... }` -/// - `declare module '@vitest/browser/{name}' { ... }` → `declare module 'vite-plus/test/browser/{name}' { ... }` -/// - `declare module '@vitest/browser-playwright' { ... }` → `declare module 'vite-plus/test/browser-playwright' { ... }` -/// - `declare module '@vitest/browser-playwright/{name}' { ... }` → `declare module 'vite-plus/test/browser-playwright/{name}' { ... }` -/// - `declare module '@vitest/browser-preview' { ... }` → `declare module 'vite-plus/test/browser-preview' { ... }` -/// - `declare module '@vitest/browser-preview/{name}' { ... }` → `declare module 'vite-plus/test/browser-preview/{name}' { ... }` -/// - `declare module '@vitest/browser-webdriverio' { ... }` → `declare module 'vite-plus/test/browser-webdriverio' { ... }` -/// - `declare module '@vitest/browser-webdriverio/{name}' { ... }` → `declare module 'vite-plus/test/browser-webdriverio/{name}' { ... }` +/// +/// `declare module 'vitest' { ... }` (and the subpath/`@vitest/*` variants) are +/// intentionally NOT rewritten — the `vite-plus/test*` subpaths are thin shims +/// that `export * from 'vitest'` (and the browser provider packages), so the +/// underlying type identity is upstream. Augmenting `'vite-plus/test'` would +/// only augment the shim module and would not merge into the upstream types +/// the user actually sees through their `import { expect } from 'vite-plus/test'` +/// statements. Leaving the `declare module 'vitest' { ... }` alone keeps +/// augmentations targeting the real upstream module identity. const REWRITE_VITEST_RULES: &str = r#"--- id: rewrite-vitest-config-import language: TypeScript @@ -174,70 +172,6 @@ transform: replace: vitest/ by: "vite-plus/test/" fix: $NEW_IMPORT ---- -id: rewrite-declare-module-vitest-config -language: TypeScript -rule: - pattern: $STR - kind: string - regex: ^['\"]vitest/config['\"]$ - inside: - kind: module -transform: - NEW_IMPORT: - replace: - source: $STR - replace: vitest/config - by: "vite-plus" -fix: $NEW_IMPORT ---- -id: rewrite-declare-module-vitest -language: TypeScript -rule: - pattern: $STR - kind: string - regex: ^['\"]vitest['\"]$ - inside: - kind: module -transform: - NEW_IMPORT: - replace: - source: $STR - replace: vitest - by: "vite-plus/test" -fix: $NEW_IMPORT ---- -id: rewrite-declare-module-vitest-scoped -language: TypeScript -rule: - pattern: $STR - kind: string - regex: ^['\"]@vitest/(browser-playwright|browser-preview|browser-webdriverio|browser)(/.*)?['\"]$ - inside: - kind: module -transform: - NEW_IMPORT: - replace: - source: $STR - replace: "@vitest/" - by: "vite-plus/test/" -fix: $NEW_IMPORT ---- -id: rewrite-declare-module-vitest-subpath -language: TypeScript -rule: - pattern: $STR - kind: string - regex: ^['\"]vitest/.+['\"]$ - inside: - kind: module -transform: - NEW_IMPORT: - replace: - source: $STR - replace: vitest/ - by: "vite-plus/test/" -fix: $NEW_IMPORT "#; /// ast-grep rules for rewriting tsdown imports and declare module statements @@ -1468,6 +1402,9 @@ describe('app', () => { #[test] fn test_rewrite_declare_module_vitest() { + // `declare module 'vitest'` is intentionally NOT rewritten — the + // `vite-plus/test` subpath is a thin shim that re-exports vitest's + // types, so augmentations must target the upstream module identity. let content = r#"declare module 'vitest' { interface JestAssertion { toBeCustom(): void; @@ -1475,19 +1412,15 @@ describe('app', () => { }"#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"declare module 'vite-plus/test' { - interface JestAssertion { - toBeCustom(): void; - } -}"# - ); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] fn test_rewrite_declare_module_vitest_config() { + // `declare module 'vitest/config'` is intentionally NOT rewritten — + // `vite-plus` re-exports `vitest/config`, so augmentations must target + // the upstream module identity to merge correctly. let content = r#"declare module 'vitest/config' { interface UserConfig { test?: TestConfig; @@ -1495,15 +1428,8 @@ describe('app', () => { }"#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"declare module 'vite-plus' { - interface UserConfig { - test?: TestConfig; - } -}"# - ); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] @@ -1528,6 +1454,9 @@ describe('app', () => { #[test] fn test_rewrite_declare_module_vitest_subpath() { + // `declare module 'vitest/node'` stays — the `vite-plus/test/node` + // shim re-exports from upstream, so augmentations must target the + // upstream module identity. let content = r#"declare module 'vitest/node' { export interface VitestOptions { custom?: boolean; @@ -1535,19 +1464,14 @@ describe('app', () => { }"#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"declare module 'vite-plus/test/node' { - export interface VitestOptions { - custom?: boolean; - } -}"# - ); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] fn test_rewrite_declare_module_vitest_browser() { + // `declare module '@vitest/browser'` stays — the + // `vite-plus/test/browser` shim re-exports from upstream. let content = r#"declare module '@vitest/browser' { interface BrowserContext { custom?: boolean; @@ -1555,19 +1479,13 @@ describe('app', () => { }"#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"declare module 'vite-plus/test/browser' { - interface BrowserContext { - custom?: boolean; - } -}"# - ); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] fn test_rewrite_declare_module_vitest_browser_subpath() { + // `declare module '@vitest/browser/context'` stays — shim re-exports. let content = r#"declare module '@vitest/browser/context' { export interface Context { custom?: boolean; @@ -1575,19 +1493,13 @@ describe('app', () => { }"#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"declare module 'vite-plus/test/browser/context' { - export interface Context { - custom?: boolean; - } -}"# - ); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] fn test_rewrite_declare_module_vitest_browser_playwright() { + // `declare module '@vitest/browser-playwright'` stays — shim re-exports. let content = r#"declare module '@vitest/browser-playwright' { interface PlaywrightContext { custom?: boolean; @@ -1595,19 +1507,13 @@ describe('app', () => { }"#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"declare module 'vite-plus/test/browser-playwright' { - interface PlaywrightContext { - custom?: boolean; - } -}"# - ); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] fn test_rewrite_declare_module_vitest_browser_preview() { + // `declare module '@vitest/browser-preview'` stays — shim re-exports. let content = r#"declare module '@vitest/browser-preview' { interface PreviewContext { custom?: boolean; @@ -1615,19 +1521,13 @@ describe('app', () => { }"#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"declare module 'vite-plus/test/browser-preview' { - interface PreviewContext { - custom?: boolean; - } -}"# - ); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] fn test_rewrite_declare_module_vitest_browser_webdriverio() { + // `declare module '@vitest/browser-webdriverio'` stays — shim re-exports. let content = r#"declare module '@vitest/browser-webdriverio' { interface WebDriverContext { custom?: boolean; @@ -1635,19 +1535,16 @@ describe('app', () => { }"#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"declare module 'vite-plus/test/browser-webdriverio' { - interface WebDriverContext { - custom?: boolean; - } -}"# - ); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] fn test_rewrite_mixed_imports_and_declare_modules() { + // Imports are rewritten; `declare module 'vite' { ... }` is rewritten + // (vite-plus bundles vite, owning the type identity), but + // `declare module 'vitest' { ... }` stays put — the shim re-exports + // upstream and augmentations must target the upstream identity. let content = r#"import { defineConfig } from 'vite'; import { describe } from 'vitest'; @@ -1678,7 +1575,7 @@ declare module 'vite-plus' { } } -declare module 'vite-plus/test' { +declare module 'vitest' { interface JestAssertion { toBeCustom(): void; } @@ -1703,6 +1600,10 @@ export default defineConfig({});"# #[test] fn test_rewrite_multiple_declare_modules() { + // `declare module 'vite'` / `'vite/'` get rewritten (vite-plus + // bundles vite, owning the type identity), but `declare module 'vitest'` + // and `declare module '@vitest/browser'` are preserved — vite-plus + // shims re-export upstream and augmentations must target upstream. let content = r#"declare module 'vite' { interface UserConfig { custom?: boolean; @@ -1743,13 +1644,13 @@ declare module 'vite-plus/module-runner' { } } -declare module 'vite-plus/test' { +declare module 'vitest' { interface JestAssertion { toBeCustom(): void; } } -declare module 'vite-plus/test/browser' { +declare module '@vitest/browser' { interface BrowserContext { custom?: boolean; } @@ -1759,6 +1660,8 @@ declare module 'vite-plus/test/browser' { #[test] fn test_rewrite_declare_module_vitest_double_quotes() { + // Double-quoted `declare module "vitest"` is preserved for the same + // reason as the single-quoted variant — shim re-exports. let content = r#"declare module "vitest" { interface JestAssertion { toBeCustom(): void; @@ -1766,15 +1669,8 @@ declare module 'vite-plus/test/browser' { }"#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"declare module "vite-plus/test" { - interface JestAssertion { - toBeCustom(): void; - } -}"# - ); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] @@ -1786,15 +1682,8 @@ declare module 'vite-plus/test/browser' { }"#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"declare module 'vite-plus/test/browser-playwright/context' { - export interface Context { - custom?: boolean; - } -}"# - ); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] @@ -1806,15 +1695,8 @@ declare module 'vite-plus/test/browser' { }"#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"declare module 'vite-plus/test/browser-preview/context' { - export interface Context { - custom?: boolean; - } -}"# - ); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] @@ -1826,15 +1708,8 @@ declare module 'vite-plus/test/browser' { }"#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"declare module 'vite-plus/test/browser-webdriverio/context' { - export interface Context { - custom?: boolean; - } -}"# - ); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] diff --git a/packages/cli/build.ts b/packages/cli/build.ts index 9248371fc8..4f01808273 100644 --- a/packages/cli/build.ts +++ b/packages/cli/build.ts @@ -46,6 +46,20 @@ const BROWSER_PROVIDER_PACKAGES: ReadonlyArray<{ pkg: string; short: string }> = { pkg: '@vitest/browser-webdriverio', short: 'webdriverio' }, ]; +/** + * Vitest-related bare specifiers that appear in `@vitest/browser-*` d.ts files + * and the sub-path under `dist/test/` whose shim re-exports the same module. + * Longer prefixes are listed first so substring matches don't shadow them + * (e.g. `vitest/internal/browser` before `vitest/browser`). + */ +const VITEST_TYPE_SPECIFIER_REWRITES: ReadonlyArray = [ + ['@vitest/browser/context', '_at-vitest-browser/context'], + ['@vitest/browser', '_at-vitest-browser'], + ['vitest/internal/browser', 'internal/browser'], + ['vitest/browser', 'browser'], + ['vitest/node', 'node'], +]; + const { values: { ['skip-native']: skipNative, ['skip-ts']: skipTs }, } = parseArgs({ @@ -341,6 +355,13 @@ async function syncTestPackageExports() { } } + // Private shims for `@vitest/browser` and `@vitest/browser/context`. These + // are referenced as relative paths from the inlined browser-provider d.ts + // shims so that `@vitest/browser` resolves through vite-plus's own pnpm-edge + // (same one that owns the `vitest` direct dep) — preventing the two-vitest + // type-identity split that breaks user `provider: playwright()` typechecks. + await writePrivateAtVitestBrowserShims(testDistDir); + // Mirror upstream @vitest/browser-* provider packages under ./test/ and // ./test/browser/providers/. Existing vite-plus user code imports from these // paths (e.g., `vite-plus/test/browser-playwright`) and must keep resolving after @@ -354,6 +375,7 @@ async function syncTestPackageExports() { continue; } const providerPkg = JSON.parse(await readFile(providerPkgPath, 'utf-8')); + const providerPkgRoot = dirname(providerPkgPath); const providerExports = (providerPkg.exports ?? {}) as Record; for (const [providerExportPath, providerExportValue] of Object.entries(providerExports)) { @@ -386,6 +408,7 @@ async function syncTestPackageExports() { providerExportValue, importSpecifier, testDistDir, + { providerPkgRoot }, ); if (shimExport) { generatedExports[cliPath] = shimExport; @@ -543,6 +566,113 @@ type ExportValue = node?: string; }; +/** + * Write private shims at `dist/test/_at-vitest-browser{.d.ts,/context.d.ts}` + * that re-export the `@vitest/browser` package. These are referenced by the + * inlined browser-provider d.ts shims via relative paths so all of + * `@vitest/browser`, `vitest/node`, etc. resolve through vite-plus's own + * pnpm-edge — the same edge that owns vite-plus's `vitest` direct dep. + * The underscore prefix marks them as private; they are not surfaced in the + * package.json `exports` map (TS resolves the relative paths directly). + */ +async function writePrivateAtVitestBrowserShims(testDistDir: string): Promise { + await mkdir(join(testDistDir, '_at-vitest-browser'), { recursive: true }); + await writeFile( + join(testDistDir, '_at-vitest-browser.d.ts'), + `import '@vitest/browser';\nexport * from '@vitest/browser';\n`, + ); + await writeFile( + join(testDistDir, '_at-vitest-browser/context.d.ts'), + `import '@vitest/browser/context';\nexport * from '@vitest/browser/context';\n`, + ); +} + +/** + * Inline-copy a browser-provider's upstream `.d.ts` file into `outDtsPath` and + * rewrite vitest-related bare specifiers to relative paths inside the + * vite-plus test shim tree. See `VITEST_TYPE_SPECIFIER_REWRITES` and + * `writePrivateAtVitestBrowserShims` for the rationale. + * + * Specifiers that are user peer dependencies (`playwright`, `webdriverio`, + * `tinyrainbow`, etc.) and the `@vitest/browser-*` self-import are left bare. + */ +async function writeInlinedProviderDts( + outDtsPath: string, + upstreamDtsPath: string, + testDistDir: string, +): Promise { + const upstream = await readFile(upstreamDtsPath, 'utf-8'); + const outDir = dirname(outDtsPath); + // Resolve to the file basename appended to the relative dir, never to the + // bare directory. `relative('dist/test/x/', 'dist/test/y')` returns `'../y'` + // but `relative('dist/test/x/', 'dist/test/y/')` returns `'..'` — TS would + // then look for `dist/test/y/index.d.ts` instead of `dist/test/y.d.ts`. We + // always emit `/` so the basename lookup hits the file. + const relToShim = (sub: string): string => { + const r = relative(outDir, testDistDir).replaceAll('\\', '/'); + const prefix = r === '' ? '.' : r.startsWith('.') ? r : `./${r}`; + return `${prefix}/${sub}`; + }; + let result = upstream; + for (const [bare, sub] of VITEST_TYPE_SPECIFIER_REWRITES) { + const escaped = bare.replaceAll('/', '\\/'); + const pattern = new RegExp(`(['"])${escaped}\\1`, 'g'); + result = result.replaceAll(pattern, `'${relToShim(sub)}'`); + } + await mkdir(outDir, { recursive: true }); + await writeFile(outDtsPath, result); +} + +/** + * Resolve the upstream `.d.ts` path for a given export value. Returns null + * when the export does not declare a types file (runtime-only exports). + */ +function resolveUpstreamDtsPath( + providerPkgRoot: string, + exportValue: unknown, + condition: 'types' | 'require-types' = 'types', +): string | null { + if (typeof exportValue === 'string') { + return exportValue.endsWith('.d.ts') || exportValue.endsWith('.d.cts') + ? join(providerPkgRoot, exportValue) + : null; + } + if (typeof exportValue !== 'object' || exportValue === null) { + return null; + } + const value = exportValue as Record; + if (condition === 'types') { + if (typeof value.types === 'string') return join(providerPkgRoot, value.types); + if (typeof value.import === 'object' && value.import !== null) { + const types = (value.import as Record).types; + if (typeof types === 'string') return join(providerPkgRoot, types); + } + } else { + if (typeof value.require === 'object' && value.require !== null) { + const types = (value.require as Record).types; + if (typeof types === 'string') return join(providerPkgRoot, types); + } + } + return null; +} + +async function writeShimDts( + outDtsPath: string, + importSpecifier: string, + upstreamDtsPath: string | null, + testDistDir: string, +): Promise { + if (upstreamDtsPath) { + await writeInlinedProviderDts(outDtsPath, upstreamDtsPath, testDistDir); + return; + } + // Include side-effect import to preserve module augmentations (e.g., toMatchSnapshot on Assertion) + await writeFile( + outDtsPath, + `import '${importSpecifier}';\nexport * from '${importSpecifier}';\n`, + ); +} + /** * Create shim file(s) for a single export and return the export entry for package.json. * @@ -551,12 +681,15 @@ type ExportValue = * @param testImportSpecifier The bare import specifier the shim should re-export from * (e.g. 'vitest', 'vitest/node', '@vitest/browser-playwright'). * @param distDir Output dist/test directory. + * @param opts Optional shim context. Pass `providerPkgRoot` for browser-provider + * packages to inline-copy their upstream d.ts content with specifier rewrites. */ async function createShimForExport( shimBaseName: string, exportValue: unknown, testImportSpecifier: string, distDir: string, + opts: { providerPkgRoot?: string } = {}, ): Promise { const shimDir = join(distDir, dirname(shimBaseName)); await mkdir(shimDir, { recursive: true }); @@ -570,11 +703,10 @@ async function createShimForExport( // Check if it's a type-only export if (exportValue.endsWith('.d.ts')) { const dtsPath = join(shimDirForFile, `${baseFileName}.d.ts`); - // Include side-effect import to preserve module augmentations (e.g., toMatchSnapshot on Assertion) - await writeFile( - dtsPath, - `import '${testImportSpecifier}';\nexport * from '${testImportSpecifier}';\n`, - ); + const upstream = opts.providerPkgRoot + ? resolveUpstreamDtsPath(opts.providerPkgRoot, exportValue, 'types') + : null; + await writeShimDts(dtsPath, testImportSpecifier, upstream, distDir); return { types: `./dist/test/${shimBaseName}.d.ts` }; } @@ -594,6 +726,8 @@ async function createShimForExport( shimDirForFile, baseFileName, shimBaseName, + distDir, + opts, ); } @@ -602,11 +736,10 @@ async function createShimForExport( if (value.types && typeof value.types === 'string') { const dtsPath = join(shimDirForFile, `${baseFileName}.d.ts`); - // Include side-effect import to preserve module augmentations (e.g., toMatchSnapshot on Assertion) - await writeFile( - dtsPath, - `import '${testImportSpecifier}';\nexport * from '${testImportSpecifier}';\n`, - ); + const upstream = opts.providerPkgRoot + ? resolveUpstreamDtsPath(opts.providerPkgRoot, value, 'types') + : null; + await writeShimDts(dtsPath, testImportSpecifier, upstream, distDir); (result as Record).types = `./dist/test/${shimBaseName}.d.ts`; } @@ -641,6 +774,8 @@ async function createConditionalShim( shimDir: string, baseFileName: string, shimBaseName: string, + distDir: string, + opts: { providerPkgRoot?: string } = {}, ): Promise { // Build entries as an array of tuples so we control insertion order explicitly. // Final order for flat entries: types, import (if present), require, default. @@ -651,11 +786,10 @@ async function createConditionalShim( // Handle top-level types (flat structure like { types, require, default }) if (value.types && typeof value.types === 'string' && !value.import) { const dtsPath = join(shimDir, `${baseFileName}.d.ts`); - // Include side-effect import to preserve module augmentations (e.g., toMatchSnapshot on Assertion) - await writeFile( - dtsPath, - `import '${testImportSpecifier}';\nexport * from '${testImportSpecifier}';\n`, - ); + const upstream = opts.providerPkgRoot + ? resolveUpstreamDtsPath(opts.providerPkgRoot, value, 'types') + : null; + await writeShimDts(dtsPath, testImportSpecifier, upstream, distDir); entries.push(['types', `./dist/test/${shimBaseName}.d.ts`]); } @@ -672,11 +806,10 @@ async function createConditionalShim( if (importValue.types && typeof importValue.types === 'string') { const dtsPath = join(shimDir, `${baseFileName}.d.ts`); - // Include side-effect import to preserve module augmentations (e.g., toMatchSnapshot on Assertion) - await writeFile( - dtsPath, - `import '${testImportSpecifier}';\nexport * from '${testImportSpecifier}';\n`, - ); + const upstream = opts.providerPkgRoot + ? resolveUpstreamDtsPath(opts.providerPkgRoot, value, 'types') + : null; + await writeShimDts(dtsPath, testImportSpecifier, upstream, distDir); importResult.types = `./dist/test/${shimBaseName}.d.ts`; } @@ -709,11 +842,10 @@ async function createConditionalShim( if (requireValue.types && typeof requireValue.types === 'string') { const dctsPath = join(shimDir, `${baseFileName}.d.cts`); - // Include side-effect import to preserve module augmentations (e.g., toMatchSnapshot on Assertion) - await writeFile( - dctsPath, - `import '${testImportSpecifier}';\nexport * from '${testImportSpecifier}';\n`, - ); + const upstream = opts.providerPkgRoot + ? resolveUpstreamDtsPath(opts.providerPkgRoot, value, 'require-types') + : null; + await writeShimDts(dctsPath, testImportSpecifier, upstream, distDir); requireResult.types = `./dist/test/${shimBaseName}.d.cts`; } diff --git a/packages/cli/src/migration/migrator.ts b/packages/cli/src/migration/migrator.ts index 030f91028a..cde969412d 100644 --- a/packages/cli/src/migration/migrator.ts +++ b/packages/cli/src/migration/migrator.ts @@ -1677,6 +1677,11 @@ function rewriteRootWorkspacePackageJson( }; }; }>(packageJsonPath, (pkg) => { + // Strip stale `vite-plus-test` wrapper aliases before injecting new overrides + // so the deleted wrapper doesn't survive migration in any sink. + pruneLegacyWrapperAliases(pkg.resolutions); + pruneLegacyWrapperAliases(pkg.overrides); + pruneLegacyWrapperAliases(pkg.pnpm?.overrides); if (packageManager === PackageManager.yarn) { pkg.resolutions = { ...pkg.resolutions, From 525c965e657e95deb43a93e32204a524f50d4e07 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 15 May 2026 20:58:18 +0800 Subject: [PATCH 05/37] fix(migration): emit bunfig.toml with peer = false to unblock bun installs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vitest@4.1.5 declares a `vite^6/^7/^8` peer dep. When the user's project overrides `vite` to `@voidzero-dev/vite-plus-core` (version 0.0.0 in dev and 0.1.21 on npm — neither matches), bun aborts with: error: vite@^6.0.0 || ^7.0.0 || ^8.0.0 failed to resolve pnpm/yarn/npm tolerate this redirect; bun does not, and offers no `peerDependencyRules`-style escape hatch — only `[install] peer = false` in `bunfig.toml`. vite-plus already provides the vite surface the user needs, so disabling bun's auto-install of *missing* peers is safe here: the redirected vite is the only one that ever fails, and other vitest peers (jsdom, happy-dom, @vitest/*, etc.) are upstream-optional and either pulled in transitively or user-installed. `ensureBunfigPeerSuppression` writes/merges `bunfig.toml` whenever the migrator touches a bun project — both the monorepo path (via `rewriteBunCatalog`) and the standalone path (in `rewriteStandaloneProject`'s post-package.json branch). Honors any pre-existing `peer =` setting so a user who deliberately set `peer = true` keeps it. Co-Authored-By: Claude Opus 4.7 --- .../new-vite-monorepo-bun/snap.txt | 1 + .../bun-catalog-file-protocol.spec.ts | 58 +++++++++++++++++++ packages/cli/src/migration/migrator.ts | 40 +++++++++++++ 3 files changed, 99 insertions(+) diff --git a/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt b/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt index 96f4a2dd37..cb7003bc15 100644 --- a/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt +++ b/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt @@ -3,6 +3,7 @@ AGENTS.md README.md apps +bunfig.toml package.json packages tsconfig.json diff --git a/packages/cli/src/migration/__tests__/bun-catalog-file-protocol.spec.ts b/packages/cli/src/migration/__tests__/bun-catalog-file-protocol.spec.ts index 80e00bc6a1..d2d773fa75 100644 --- a/packages/cli/src/migration/__tests__/bun-catalog-file-protocol.spec.ts +++ b/packages/cli/src/migration/__tests__/bun-catalog-file-protocol.spec.ts @@ -123,6 +123,64 @@ describe('rewriteMonorepo bun catalog with file: protocol', () => { expect(pkg.devDependencies.vite).toBe('file:/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz'); }); + it('writes bunfig.toml with `peer = false` so vitest peer-dep on vite does not break install', () => { + // vitest@4.1.5 declares peer vite^6/^7/^8. With overrides.vite pointing at + // file:vite-plus-core@0.0.0 (whose package.json version does not match), + // bun aborts the install. pnpm/yarn/npm tolerate this; bun has no equivalent + // to pnpm's peerDependencyRules and only respects the `[install] peer = false` + // setting in bunfig.toml. The migrator must emit that file or every bun + // user hits `error: vite@^6.0.0 || ^7.0.0 || ^8.0.0 failed to resolve`. + fs.writeFileSync( + path.join(tmpDir, 'package.json'), + JSON.stringify({ + name: 'bun-monorepo', + workspaces: ['packages/*'], + packageManager: 'bun@1.3.11', + }), + ); + rewriteMonorepo(makeWorkspaceInfo(tmpDir, PackageManager.bun), true); + + const bunfigPath = path.join(tmpDir, 'bunfig.toml'); + expect(fs.existsSync(bunfigPath)).toBe(true); + expect(fs.readFileSync(bunfigPath, 'utf8')).toMatch(/^\[install\][\s\S]*peer\s*=\s*false/m); + }); + + it('preserves an existing bunfig.toml `peer` setting (does not overwrite user intent)', () => { + fs.writeFileSync( + path.join(tmpDir, 'package.json'), + JSON.stringify({ + name: 'bun-monorepo', + workspaces: ['packages/*'], + packageManager: 'bun@1.3.11', + }), + ); + fs.writeFileSync(path.join(tmpDir, 'bunfig.toml'), '[install]\npeer = true\n'); + rewriteMonorepo(makeWorkspaceInfo(tmpDir, PackageManager.bun), true); + + // User's explicit `peer = true` should remain — we don't silently flip it. + expect(fs.readFileSync(path.join(tmpDir, 'bunfig.toml'), 'utf8')).toMatch(/peer\s*=\s*true/); + }); + + it('appends `peer = false` under an existing [install] section without `peer` setting', () => { + fs.writeFileSync( + path.join(tmpDir, 'package.json'), + JSON.stringify({ + name: 'bun-monorepo', + workspaces: ['packages/*'], + packageManager: 'bun@1.3.11', + }), + ); + fs.writeFileSync( + path.join(tmpDir, 'bunfig.toml'), + '[install]\nregistry = "https://registry.npmjs.org/"\n', + ); + rewriteMonorepo(makeWorkspaceInfo(tmpDir, PackageManager.bun), true); + + const bunfig = fs.readFileSync(path.join(tmpDir, 'bunfig.toml'), 'utf8'); + expect(bunfig).toMatch(/registry\s*=\s*"https:\/\/registry\.npmjs\.org\/"/); + expect(bunfig).toMatch(/peer\s*=\s*false/); + }); + it('does not write file: paths into peer dependencies', () => { const pkg = { peerDependencies: { diff --git a/packages/cli/src/migration/migrator.ts b/packages/cli/src/migration/migrator.ts index cde969412d..562f1c3424 100644 --- a/packages/cli/src/migration/migrator.ts +++ b/packages/cli/src/migration/migrator.ts @@ -1010,6 +1010,8 @@ export function rewriteStandaloneProject( if (packageManager === PackageManager.yarn) { rewriteYarnrcYml(projectPath); + } else if (packageManager === PackageManager.bun) { + ensureBunfigPeerSuppression(projectPath); } // Merge extracted staged config into vite.config.ts, then remove lint-staged from package.json @@ -1577,6 +1579,42 @@ function rewriteCatalogsObject(catalogs: Record>) } } +/** + * Bun rejects vitest@4.1.5's `vite^6/^7/^8` peer-dep when the user's project + * overrides `vite` to `@voidzero-dev/vite-plus-core` (whose package.json version + * does not match those ranges). pnpm/yarn/npm all tolerate this redirect; bun + * does not, and there is no `peerDependencyRules`-style escape hatch — only the + * `[install] peer = false` setting in `bunfig.toml`. + * + * `vite-plus`/`@voidzero-dev/vite-plus-core` already provide the vite surface + * the user needs, so disabling bun's auto-install of *missing* peers is safe in + * this configuration: any vitest peer that's not already pulled in transitively + * (jsdom, happy-dom, etc.) is marked optional upstream anyway. + * + * Writes/merges `bunfig.toml` at `projectPath` so the suppression applies on + * the migration's reinstall AND every subsequent `bun install` the user runs. + */ +function ensureBunfigPeerSuppression(projectPath: string): void { + const bunfigPath = path.join(projectPath, 'bunfig.toml'); + const block = '[install]\npeer = false\n'; + if (!fs.existsSync(bunfigPath)) { + fs.writeFileSync(bunfigPath, block); + return; + } + const existing = fs.readFileSync(bunfigPath, 'utf8'); + // Already configured? Leave the user's setting alone — they may have set + // `peer = true` deliberately for some other reason and we shouldn't override. + if (/^\s*peer\s*=\s*(true|false)\s*$/m.test(existing)) { + return; + } + // Append under existing [install] section, or add a new section. + const installSectionRe = /^\[install\][^[]*/m; + const next = installSectionRe.test(existing) + ? existing.replace(installSectionRe, (section) => `${section.trimEnd()}\npeer = false\n`) + : `${existing.trimEnd()}\n\n${block}`; + fs.writeFileSync(bunfigPath, next); +} + /** * Write catalog entries to root package.json for bun. * Bun stores catalogs in package.json under the `catalog` key, @@ -1644,6 +1682,8 @@ function rewriteBunCatalog(projectPath: string): void { return pkg; }); + + ensureBunfigPeerSuppression(projectPath); } /** From e86af6007345198e7600544aab29bd701567742c Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 15 May 2026 21:10:00 +0800 Subject: [PATCH 06/37] docs: align migrate guide and bundling notes with actual rewrite/shim behavior MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Earlier drafts of this branch claimed the migrator stopped rewriting `vitest` runtime imports and that the browser-provider subpaths were no longer re-exported. That landed in docs/guide/migrate.md, rfcs/migration-command.md, and packages/cli/BUNDLING.md, but the implementation kept the forward rewrites (`vitest` → `vite-plus/test`, `@vitest/browser*` → `vite-plus/test/browser*`) and added the inlined-d.ts shim infrastructure that *does* re-export every provider subpath under both `./test/` and `./test/browser/providers/`. The only thing actually preserved is `declare module 'vitest'` / `declare module '@vitest/browser*'` — those have to target the upstream module identity to merge into the types `vite-plus/test*` re-exports. This commit restores the migrate guide's "import { vi } from 'vite-plus/test'" example, restores the full rewrite-rule list in the migration-command RFC, fixes the bundling doc's "provider subpaths are not re-exported" claim, and adds a short subsection explaining why the provider d.ts shims are inlined instead of bare re-exports (the pnpm-edge type-identity split that would otherwise break user `provider: playwright()` typechecks). Co-Authored-By: Claude Opus 4.7 --- docs/guide/migrate.md | 24 +++++++++++------------- packages/cli/BUNDLING.md | 35 +++++++++++++++++++++++++++++------ rfcs/migration-command.md | 8 +++++++- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/docs/guide/migrate.md b/docs/guide/migrate.md index 36ca03ebcc..3ea26aa27d 100644 --- a/docs/guide/migrate.md +++ b/docs/guide/migrate.md @@ -75,8 +75,8 @@ Migrate this project to Vite+. Vite+ replaces the current split tooling around r After the migration: - Confirm `vite` imports were rewritten to `vite-plus` where needed -- Confirm `vitest/config` imports were rewritten to `vite-plus` (other `vitest` and `@vitest/browser*` imports are intentionally left as-is) -- Remove the old `vite` dependency only after those rewrites are confirmed; keep `vitest` and any `@vitest/browser*` providers +- Confirm `vitest` imports were rewritten to `vite-plus/test` (and `@vitest/browser*` to `vite-plus/test/browser*`) where needed +- Remove old `vite`, `vitest`, and `@vitest/browser*` dependencies only after those rewrites are confirmed — `vite-plus` ships them as direct deps - Move remaining tool-specific config into the appropriate blocks in `vite.config.ts` Command mapping to keep in mind: @@ -96,27 +96,25 @@ Summarize the migration at the end and report any manual follow-up still require ### Vitest -`vp migrate` is the recommended path. It only rewrites `vitest/config` imports to `vite-plus`; all other Vitest imports are left untouched and resolve through the upstream `vitest` package as usual (`vite` is aliased to `@voidzero-dev/vite-plus-core` via overrides, so Vitest picks up the Vite+ core transparently). - -If you are migrating manually, update only the config entry point: +Vitest is automatically migrated through `vp migrate`. `vite-plus` re-exports upstream `vitest@4.x` under `vite-plus/test*` (including the browser-provider subpaths), so a single `vite-plus` install is enough — you no longer need to install `vitest` or any `@vitest/browser*` provider directly. If you are migrating manually, update all the imports to `vite-plus/test*` instead: ```ts // before import { defineConfig } from 'vitest/config'; +import { describe, expect, it, vi } from 'vitest'; +import { playwright } from '@vitest/browser-playwright'; + +const { page } = await import('@vitest/browser/context'); // after import { defineConfig } from 'vite-plus'; -``` +import { describe, expect, it, vi } from 'vite-plus/test'; +import { playwright } from 'vite-plus/test/browser-playwright'; -Runtime imports stay as-is: - -```ts -import { describe, expect, it, vi } from 'vitest'; - -const { page } = await import('@vitest/browser/context'); +const { page } = await import('vite-plus/test/browser/context'); ``` -Do not rewrite bare `vitest`, `vitest/*` subpaths, or `@vitest/browser*` — Vitest's mock hoister requires the literal string `'vitest'`, and the browser/provider subpaths are not re-exported by `vite-plus`. +`declare module 'vitest'` / `declare module '@vitest/browser*'` augmentations are intentionally **not** rewritten — `vite-plus/test*` is a thin re-export of upstream `vitest*`, so type augmentations have to target the upstream module identity to merge correctly. Leave those `declare module` statements pointing at `'vitest'` / `'@vitest/browser*'`. ### tsdown diff --git a/packages/cli/BUNDLING.md b/packages/cli/BUNDLING.md index 7067afb7c9..ad91b570f9 100644 --- a/packages/cli/BUNDLING.md +++ b/packages/cli/BUNDLING.md @@ -90,15 +90,22 @@ export type * from '@voidzero-dev/vite-plus-core/types/importMeta.d.ts'; ### Step 4: Test Package Export Sync (`syncTestPackageExports`) -Reads vitest's exports and creates shim files that re-export everything under `./test/*`: +Reads vitest's exports plus the three `@vitest/browser-*` provider packages and creates shim files that re-export everything under `./test/*`: ```typescript -// For each vitest export like "./browser-playwright" -// Creates a shim file: dist/test/browser-playwright.js -export * from 'vitest/browser-playwright'; +// For each vitest export like "./node" +// Creates a shim file: dist/test/node.js +export * from 'vitest/node'; + +// For each @vitest/browser-* provider, two shim surfaces are projected: +// dist/test/browser-playwright.js (matches old wrapper path) +// dist/test/browser/providers/playwright.js (alias path) +export * from '@vitest/browser-playwright'; ``` -**Input**: resolved `vitest/package.json` exports (resolved via `createRequire`) +Provider `.d.ts` shims are NOT bare re-exports — see the [Provider Type Identity](#why-provider-dts-shims-are-inlined) note below. + +**Input**: resolved `vitest/package.json` exports plus each `@vitest/browser-*` package's exports (all resolved via `createRequire`) **Output**: `dist/test/*.js`, `dist/test/*.d.ts`, updated `package.json` exports --- @@ -354,7 +361,23 @@ Every entry under vitest's own `exports` is shimmed under `./test/*` (wildcard e | `vitest/config` | `vite-plus/test/config` | | `vitest/reporters` | `vite-plus/test/reporters` | -The full set is regenerated on every build from the upstream vitest `package.json`, so the exact list tracks vitest itself. Browser provider packages (`@vitest/browser-playwright`, `@vitest/browser-preview`, `@vitest/browser-webdriverio`) and `@vitest/browser/context` are **not** re-exported — consume those directly from their original specifiers. +The full set is regenerated on every build from the upstream vitest `package.json`, so the exact list tracks vitest itself. + +In addition to vitest's own exports, the three `@vitest/browser-*` provider packages are projected under two parallel surfaces so existing user code keeps resolving after the deleted `@voidzero-dev/vite-plus-test` wrapper: + +| Provider Package | CLI Package Exports | +| ----------------------------- | --------------------------------------------------------------------------- | +| `@vitest/browser-playwright` | `vite-plus/test/browser-playwright`, `vite-plus/test/browser/providers/playwright` | +| `@vitest/browser-preview` | `vite-plus/test/browser-preview`, `vite-plus/test/browser/providers/preview` | +| `@vitest/browser-webdriverio` | `vite-plus/test/browser-webdriverio`, `vite-plus/test/browser/providers/webdriverio` | + +Each provider's own subpaths (e.g. `./context`) are mirrored under both alias prefixes. + +#### Why provider d.ts shims are inlined + +Provider `.d.ts` shims are NOT plain `export * from '@vitest/browser-playwright'` re-exports — they inline the upstream `.d.ts` content with `vitest/node` / `vitest/browser` / `@vitest/browser*` bare specifiers rewritten to relative paths inside `dist/test/`. The two private shims `dist/test/_at-vitest-browser.d.ts` and `dist/test/_at-vitest-browser/context.d.ts` re-export `@vitest/browser`/`@vitest/browser/context` and are referenced from those rewrites. + +This avoids a pnpm-edge type-identity split: when the upstream `.d.ts` is loaded by reference (`export * from '@vitest/browser-playwright'`), TypeScript resolves its internal `import { BrowserProvider } from 'vitest/node'` through the provider package's own pnpm-edge, which can be a different vitest copy than the one a user's `vite.config.ts` sees through `vite-plus`. The mismatch produces two structurally identical but nominally distinct `BrowserProvider` types, so `provider: playwright()` fails the user's typecheck. Rewriting the specifiers routes every type import through vite-plus's own subpath shims, guaranteeing a single vitest identity across the user's whole config. ### Conditional Export Handling diff --git a/rfcs/migration-command.md b/rfcs/migration-command.md index 47ab4803c6..bf18611e61 100644 --- a/rfcs/migration-command.md +++ b/rfcs/migration-command.md @@ -274,8 +274,14 @@ Projects that already have a `pnpm` field in `package.json` (e.g., with `overrid - For pnpm with existing `pnpm` config in `package.json`, the existing location is respected - rewrite `import from 'vite'` to `import from 'vite-plus'` - rewrite `import from 'vite/{name}'` to `import from 'vite-plus/{name}'`, e.g.: `import from 'vite/module-runner'` to `import from 'vite-plus/module-runner'` +- rewrite `import from 'vitest'` to `import from 'vite-plus/test'` - rewrite `import from 'vitest/config'` to `import from 'vite-plus'` -- bare `vitest`, other `vitest/{name}` subpaths, and all `@vitest/browser*` imports are intentionally **not** rewritten — vite-plus consumes upstream `vitest@4.x` directly (via overrides on `vite`), Vitest's mock hoister requires the literal string `'vitest'`, and the browser/provider subpaths are not re-exported by vite-plus +- rewrite `import from 'vitest/{name}'` to `import from 'vite-plus/test/{name}'`, e.g.: `import from 'vitest/node'` to `import from 'vite-plus/test/node'` +- rewrite `import from '@vitest/browser'` to `import from 'vite-plus/test/browser'` +- rewrite `import from '@vitest/browser/{name}'` to `import from 'vite-plus/test/browser/{name}'`, e.g.: `import from '@vitest/browser/context'` to `import from 'vite-plus/test/browser/context'` +- rewrite `import from '@vitest/browser-playwright'` to `import from 'vite-plus/test/browser-playwright'` +- rewrite `import from '@vitest/browser-playwright/{name}'` to `import from 'vite-plus/test/browser-playwright/{name}'` +- `declare module 'vitest'`, `declare module 'vitest/{name}'`, and `declare module '@vitest/browser*'` are intentionally **not** rewritten — `vite-plus/test*` is a thin re-export of upstream `vitest*`, so type augmentations have to target the upstream module identity to merge correctly **Note**: For Yarn, use `resolutions` instead of `overrides`. From babeebc527a8ac008e06f6ab051ce9afdbeb119f Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 15 May 2026 21:32:59 +0800 Subject: [PATCH 07/37] fix(ci): bump core tgz version for bun, sync declare-module snap * `.github/workflows/test-vp-create.yml`: bun strictly checks override target versions against transitive peer ranges; vitest 4.1.5 declares peer `vite ^6 || ^7 || ^8` and bun aborts when the override points at the 0.0.0 tgz. Repack core with version `7.99.0` so the satisfied range is met, restore the source `package.json` before packing the CLI, and rename the tgz back to the 0.0.0 filename the env var references. * `snap-tests-global/migration-rewrite-declare-module/snap.txt`: align with the preserved-declare-module rewrite behavior (declare module 'vitest' / 'vitest/config' stay as-is; only `declare module 'vite'` still rewrites to 'vite-plus'). --- .github/workflows/test-vp-create.yml | 15 +++++++++++++++ .../migration-rewrite-declare-module/snap.txt | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-vp-create.yml b/.github/workflows/test-vp-create.yml index 6c9d5ec23c..443e66d9be 100644 --- a/.github/workflows/test-vp-create.yml +++ b/.github/workflows/test-vp-create.yml @@ -93,7 +93,22 @@ jobs: - name: Pack packages into tgz run: | mkdir -p tmp/tgz + # Bun strictly validates override-target versions against transitive + # peer constraints (vitest 4.1.5 declares peer `vite ^6 || ^7 || ^8`). + # pnpm/npm/yarn don't, but bun aborts with "vite@^6.0.0 || ^7.0.0 || + # ^8.0.0 failed to resolve" when the override points at a 0.0.0 tgz. + # See https://github.com/oven-sh/bun/issues/8406. Bump core's pack-time + # version into the satisfied range; the file is restored after pack so + # the in-repo source stays at 0.0.0. + node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. + # Restore version before packing CLI so the CLI tgz keeps the 0.0.0 + # workspace dep (the file: override in VP_OVERRIDE_PACKAGES still + # redirects @voidzero-dev/vite-plus-core to the bumped tgz regardless). + git checkout -- packages/core/package.json + # Rename core tgz back to the stable 0.0.0 filename that + # VP_OVERRIDE_PACKAGES references. + mv tmp/tgz/voidzero-dev-vite-plus-core-7.99.0.tgz tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. # Copy vp binary for test jobs cp target/x86_64-unknown-linux-gnu/release/vp tmp/tgz/vp diff --git a/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt b/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt index e49b163037..292f907310 100644 --- a/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt +++ b/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt @@ -20,7 +20,7 @@ declare module 'vite-plus' { } } -declare module 'vite-plus/test' { +declare module 'vitest' { export const describe: any; export const it: any; export const expect: any; @@ -28,7 +28,7 @@ declare module 'vite-plus/test' { export const afterAll: any; } -declare module 'vite-plus' { +declare module 'vitest/config' { export function defineConfig(config: any): any; const _default: typeof defineConfig; export default _default; From de2e9ba9c4bfa7f8fe3632d0135e4ea91444fc3f Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 15 May 2026 21:39:35 +0800 Subject: [PATCH 08/37] fix(ci): use a separate bumped-version core tgz for VP_OVERRIDE_PACKAGES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous attempt repacked core in place and restored the source package.json before packing the CLI; this left the CLI tgz declaring @voidzero-dev/vite-plus-core@0.0.0 while the override target's internal version was 7.99.0. install-global-cli (which resolves the CLI's transitive @voidzero-dev/vite-plus-core@0.0.0 dep) then asked npm for that exact version on the registry — which doesn't exist — and every non-bun vp-create job started failing. Build the bun-friendly variant as a separate tgz instead: - core-0.0.0.tgz stays untouched (install-global-cli + CLI's transitive dep both resolve against it as before) - core-bumped.tgz holds the same contents with the internal version rewritten to 7.99.0 so bun's strict peer-dep check on the override target passes - VP_OVERRIDE_PACKAGES (in test-vp-create.yml matrix env and ecosystem-ci/patch-project.ts) points at the bumped variant Background: vitest 4.1.5 declares peer `vite ^6 || ^7 || ^8` and bun strictly validates the override target's version against that range where pnpm/npm/yarn don't. See https://github.com/oven-sh/bun/issues/8406. --- .github/workflows/e2e-test.yml | 15 +++++++++++++++ .github/workflows/test-vp-create.yml | 28 ++++++++++++++-------------- ecosystem-ci/patch-project.ts | 4 ++-- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 6b7fec6924..3a240cd2b5 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -110,6 +110,21 @@ jobs: mkdir -p tmp/tgz cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. + # Bun strictly validates override-target versions against transitive + # peer constraints (vitest 4.1.5 declares peer `vite ^6 || ^7 || ^8`). + # pnpm/npm/yarn don't, but bun aborts with "vite@^6.0.0 || ^7.0.0 || + # ^8.0.0 failed to resolve" when the override points at a 0.0.0 tgz. + # See https://github.com/oven-sh/bun/issues/8406. Build a separate + # tgz with the same contents but an internal version that satisfies + # the peer range; VP_OVERRIDE_PACKAGES points the migrator at this + # variant. The original core-0.0.0.tgz is still needed verbatim so + # install-global-cli can resolve the CLI's transitive @voidzero-dev/ + # vite-plus-core@0.0.0 dep. + mkdir -p tmp/core-bumped + tar xzf tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz -C tmp/core-bumped + node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('tmp/core-bumped/package/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('tmp/core-bumped/package/package.json',JSON.stringify(p,null,2)+'\n')" + (cd tmp/core-bumped && tar czf "$GITHUB_WORKSPACE/tmp/tgz/voidzero-dev-vite-plus-core-bumped.tgz" package) + rm -rf tmp/core-bumped # Copy vp binary for e2e-test job (findVpBinary expects it in target/) cp target/${{ matrix.target }}/release/vp tmp/tgz/vp 2>/dev/null || cp target/${{ matrix.target }}/release/vp.exe tmp/tgz/vp.exe 2>/dev/null || true cp target/${{ matrix.target }}/release/vp-shim.exe tmp/tgz/vp-shim.exe 2>/dev/null || true diff --git a/.github/workflows/test-vp-create.yml b/.github/workflows/test-vp-create.yml index 443e66d9be..f5cabd31c6 100644 --- a/.github/workflows/test-vp-create.yml +++ b/.github/workflows/test-vp-create.yml @@ -93,23 +93,23 @@ jobs: - name: Pack packages into tgz run: | mkdir -p tmp/tgz + cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. + cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. # Bun strictly validates override-target versions against transitive # peer constraints (vitest 4.1.5 declares peer `vite ^6 || ^7 || ^8`). # pnpm/npm/yarn don't, but bun aborts with "vite@^6.0.0 || ^7.0.0 || # ^8.0.0 failed to resolve" when the override points at a 0.0.0 tgz. - # See https://github.com/oven-sh/bun/issues/8406. Bump core's pack-time - # version into the satisfied range; the file is restored after pack so - # the in-repo source stays at 0.0.0. - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" - cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. - # Restore version before packing CLI so the CLI tgz keeps the 0.0.0 - # workspace dep (the file: override in VP_OVERRIDE_PACKAGES still - # redirects @voidzero-dev/vite-plus-core to the bumped tgz regardless). - git checkout -- packages/core/package.json - # Rename core tgz back to the stable 0.0.0 filename that - # VP_OVERRIDE_PACKAGES references. - mv tmp/tgz/voidzero-dev-vite-plus-core-7.99.0.tgz tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz - cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. + # See https://github.com/oven-sh/bun/issues/8406. Build a separate + # tgz with the same contents but an internal version that satisfies + # the peer range; VP_OVERRIDE_PACKAGES points the migrator at this + # variant. The original core-0.0.0.tgz is still needed verbatim so + # install-global-cli can resolve the CLI's transitive @voidzero-dev/ + # vite-plus-core@0.0.0 dep. + mkdir -p tmp/core-bumped + tar xzf tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz -C tmp/core-bumped + node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('tmp/core-bumped/package/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('tmp/core-bumped/package/package.json',JSON.stringify(p,null,2)+'\n')" + (cd tmp/core-bumped && tar czf "$GITHUB_WORKSPACE/tmp/tgz/voidzero-dev-vite-plus-core-bumped.tgz" package) + rm -rf tmp/core-bumped # Copy vp binary for test jobs cp target/x86_64-unknown-linux-gnu/release/vp tmp/tgz/vp ls -la tmp/tgz @@ -166,7 +166,7 @@ jobs: - yarn - bun env: - VP_OVERRIDE_PACKAGES: '{"vite":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz","@voidzero-dev/vite-plus-core":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz"}' + VP_OVERRIDE_PACKAGES: '{"vite":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-bumped.tgz","@voidzero-dev/vite-plus-core":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-bumped.tgz"}' VP_VERSION: 'file:${{ github.workspace }}/tmp/tgz/vite-plus-0.0.0.tgz' # Force full dependency rewriting so the library template's existing # vite-plus dep gets overridden with the local tgz diff --git a/ecosystem-ci/patch-project.ts b/ecosystem-ci/patch-project.ts index 38cf1303e6..33e7b8b8c5 100644 --- a/ecosystem-ci/patch-project.ts +++ b/ecosystem-ci/patch-project.ts @@ -54,8 +54,8 @@ execSync(`${cli} migrate --no-agent --no-interactive`, { ...process.env, ...(forceFreshMigration ? { VP_FORCE_MIGRATE: '1' } : {}), VP_OVERRIDE_PACKAGES: JSON.stringify({ - vite: `file:${tgzDir}/voidzero-dev-vite-plus-core-0.0.0.tgz`, - '@voidzero-dev/vite-plus-core': `file:${tgzDir}/voidzero-dev-vite-plus-core-0.0.0.tgz`, + vite: `file:${tgzDir}/voidzero-dev-vite-plus-core-bumped.tgz`, + '@voidzero-dev/vite-plus-core': `file:${tgzDir}/voidzero-dev-vite-plus-core-bumped.tgz`, }), VP_VERSION: `file:${tgzDir}/vite-plus-0.0.0.tgz`, }, From e0501b2ec34400257bbd7bfa9ab29f0579e09237 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 10:30:42 +0800 Subject: [PATCH 09/37] fix(ci): pack core/cli with synthetic 7.99.0 version for bun peer-dep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous attempt extracted core-0.0.0.tgz, rewrote the inner version, repacked with raw \`tar czf\` and pointed VP_OVERRIDE_PACKAGES at that variant. Two problems with that: * On Windows GNU tar in Git Bash mis-parses the D:\\ path as a remote host and aborts (broken pipe), so the Build vite-plus packages job failed before tgz upload. * The raw \`tar czf\` repack appears to drop something pnpm pack would have included (the bumped tgz was ~200KB smaller than the original for a one-byte version change) and bun continued to report \`vite@^6.0.0 || ^7.0.0 || ^8.0.0 failed to resolve\` against the override target — likely because the tgz wasn't a clean npm package. Switch to bumping packages/core/package.json#version to a synthetic 7.99.0 *before* both pnpm pack calls so: * core tgz is produced by pnpm pack with the bumped internal version * cli tgz declares @voidzero-dev/vite-plus-core@7.99.0 (workspace:* resolved at pack time) — install-global-cli reads the CLI's transitive dep and looks for the matching tgz, which now exists. The source package.json is restored via git after both packs so the working tree is clean for downstream steps. VP_OVERRIDE_PACKAGES (in test-vp-create.yml env and ecosystem-ci/patch-project.ts) is updated to point at the new \`voidzero-dev-vite-plus-core-7.99.0.tgz\` filename. --- .github/workflows/e2e-test.yml | 28 ++++++++++++-------------- .github/workflows/test-vp-create.yml | 30 +++++++++++++--------------- ecosystem-ci/patch-project.ts | 4 ++-- 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 3a240cd2b5..18257eb67a 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -108,23 +108,21 @@ jobs: - name: Pack packages into tgz run: | mkdir -p tmp/tgz + # Bun strictly validates the resolved package version against + # transitive peer constraints; vitest 4.1.5 declares peer + # `vite ^6 || ^7 || ^8` and bun aborts with "vite@^6.0.0 || ^7.0.0 + # || ^8.0.0 failed to resolve" when the override target's version + # is 0.0.0. pnpm/npm/yarn don't enforce this. See + # https://github.com/oven-sh/bun/issues/8406. Pack core with a + # synthetic version inside the satisfied range, then pack the CLI + # so its workspace:* dep on core resolves to that same version + # (otherwise install-global-cli can't find the right tgz). Restore + # the source package.json afterwards so the working tree stays at + # 0.0.0 for downstream steps. + node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. - # Bun strictly validates override-target versions against transitive - # peer constraints (vitest 4.1.5 declares peer `vite ^6 || ^7 || ^8`). - # pnpm/npm/yarn don't, but bun aborts with "vite@^6.0.0 || ^7.0.0 || - # ^8.0.0 failed to resolve" when the override points at a 0.0.0 tgz. - # See https://github.com/oven-sh/bun/issues/8406. Build a separate - # tgz with the same contents but an internal version that satisfies - # the peer range; VP_OVERRIDE_PACKAGES points the migrator at this - # variant. The original core-0.0.0.tgz is still needed verbatim so - # install-global-cli can resolve the CLI's transitive @voidzero-dev/ - # vite-plus-core@0.0.0 dep. - mkdir -p tmp/core-bumped - tar xzf tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz -C tmp/core-bumped - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('tmp/core-bumped/package/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('tmp/core-bumped/package/package.json',JSON.stringify(p,null,2)+'\n')" - (cd tmp/core-bumped && tar czf "$GITHUB_WORKSPACE/tmp/tgz/voidzero-dev-vite-plus-core-bumped.tgz" package) - rm -rf tmp/core-bumped + git checkout -- packages/core/package.json # Copy vp binary for e2e-test job (findVpBinary expects it in target/) cp target/${{ matrix.target }}/release/vp tmp/tgz/vp 2>/dev/null || cp target/${{ matrix.target }}/release/vp.exe tmp/tgz/vp.exe 2>/dev/null || true cp target/${{ matrix.target }}/release/vp-shim.exe tmp/tgz/vp-shim.exe 2>/dev/null || true diff --git a/.github/workflows/test-vp-create.yml b/.github/workflows/test-vp-create.yml index f5cabd31c6..e2d28c1976 100644 --- a/.github/workflows/test-vp-create.yml +++ b/.github/workflows/test-vp-create.yml @@ -93,23 +93,21 @@ jobs: - name: Pack packages into tgz run: | mkdir -p tmp/tgz + # Bun strictly validates the resolved package version against + # transitive peer constraints; vitest 4.1.5 declares peer + # `vite ^6 || ^7 || ^8` and bun aborts with "vite@^6.0.0 || ^7.0.0 + # || ^8.0.0 failed to resolve" when the override target's version + # is 0.0.0. pnpm/npm/yarn don't enforce this. See + # https://github.com/oven-sh/bun/issues/8406. Pack core with a + # synthetic version inside the satisfied range, then pack the CLI + # so its workspace:* dep on core resolves to that same version + # (otherwise install-global-cli can't find the right tgz). Restore + # the source package.json afterwards so the working tree stays at + # 0.0.0 for downstream steps. + node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. - # Bun strictly validates override-target versions against transitive - # peer constraints (vitest 4.1.5 declares peer `vite ^6 || ^7 || ^8`). - # pnpm/npm/yarn don't, but bun aborts with "vite@^6.0.0 || ^7.0.0 || - # ^8.0.0 failed to resolve" when the override points at a 0.0.0 tgz. - # See https://github.com/oven-sh/bun/issues/8406. Build a separate - # tgz with the same contents but an internal version that satisfies - # the peer range; VP_OVERRIDE_PACKAGES points the migrator at this - # variant. The original core-0.0.0.tgz is still needed verbatim so - # install-global-cli can resolve the CLI's transitive @voidzero-dev/ - # vite-plus-core@0.0.0 dep. - mkdir -p tmp/core-bumped - tar xzf tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz -C tmp/core-bumped - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('tmp/core-bumped/package/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('tmp/core-bumped/package/package.json',JSON.stringify(p,null,2)+'\n')" - (cd tmp/core-bumped && tar czf "$GITHUB_WORKSPACE/tmp/tgz/voidzero-dev-vite-plus-core-bumped.tgz" package) - rm -rf tmp/core-bumped + git checkout -- packages/core/package.json # Copy vp binary for test jobs cp target/x86_64-unknown-linux-gnu/release/vp tmp/tgz/vp ls -la tmp/tgz @@ -166,7 +164,7 @@ jobs: - yarn - bun env: - VP_OVERRIDE_PACKAGES: '{"vite":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-bumped.tgz","@voidzero-dev/vite-plus-core":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-bumped.tgz"}' + VP_OVERRIDE_PACKAGES: '{"vite":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-7.99.0.tgz","@voidzero-dev/vite-plus-core":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-7.99.0.tgz"}' VP_VERSION: 'file:${{ github.workspace }}/tmp/tgz/vite-plus-0.0.0.tgz' # Force full dependency rewriting so the library template's existing # vite-plus dep gets overridden with the local tgz diff --git a/ecosystem-ci/patch-project.ts b/ecosystem-ci/patch-project.ts index 33e7b8b8c5..47320f13c9 100644 --- a/ecosystem-ci/patch-project.ts +++ b/ecosystem-ci/patch-project.ts @@ -54,8 +54,8 @@ execSync(`${cli} migrate --no-agent --no-interactive`, { ...process.env, ...(forceFreshMigration ? { VP_FORCE_MIGRATE: '1' } : {}), VP_OVERRIDE_PACKAGES: JSON.stringify({ - vite: `file:${tgzDir}/voidzero-dev-vite-plus-core-bumped.tgz`, - '@voidzero-dev/vite-plus-core': `file:${tgzDir}/voidzero-dev-vite-plus-core-bumped.tgz`, + vite: `file:${tgzDir}/voidzero-dev-vite-plus-core-7.99.0.tgz`, + '@voidzero-dev/vite-plus-core': `file:${tgzDir}/voidzero-dev-vite-plus-core-7.99.0.tgz`, }), VP_VERSION: `file:${tgzDir}/vite-plus-0.0.0.tgz`, }, From 4f1539fc441e8857cf1da3edf4ff7bbbc25f66e2 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 10:36:02 +0800 Subject: [PATCH 10/37] docs(cli): reformat BUNDLING.md provider-exports table vp check failed in CLI E2E test on the previous commit because the provider-exports markdown table separator row was a few dashes short of matching the widest cell. Run vp check --fix to re-align. --- packages/cli/BUNDLING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/BUNDLING.md b/packages/cli/BUNDLING.md index ad91b570f9..9e97564007 100644 --- a/packages/cli/BUNDLING.md +++ b/packages/cli/BUNDLING.md @@ -365,8 +365,8 @@ The full set is regenerated on every build from the upstream vitest `package.jso In addition to vitest's own exports, the three `@vitest/browser-*` provider packages are projected under two parallel surfaces so existing user code keeps resolving after the deleted `@voidzero-dev/vite-plus-test` wrapper: -| Provider Package | CLI Package Exports | -| ----------------------------- | --------------------------------------------------------------------------- | +| Provider Package | CLI Package Exports | +| ----------------------------- | ------------------------------------------------------------------------------------ | | `@vitest/browser-playwright` | `vite-plus/test/browser-playwright`, `vite-plus/test/browser/providers/playwright` | | `@vitest/browser-preview` | `vite-plus/test/browser-preview`, `vite-plus/test/browser/providers/preview` | | `@vitest/browser-webdriverio` | `vite-plus/test/browser-webdriverio`, `vite-plus/test/browser/providers/webdriverio` | From ca1f792985f0572e4c2735f0b0fd4b1603e4276f Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 10:43:13 +0800 Subject: [PATCH 11/37] fix(migration): mirror vite override as devDep on bun MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bun walks transitive peer-deps before resolving overrides. vitest@4.1.5 declares peer \`vite ^6 || ^7 || ^8\` and aborts with "vite@... failed to resolve" if \`vite\` isn't a direct dep somewhere in the tree, even when the user's overrides would redirect it to vite-plus-core. pnpm, npm, and yarn don't enforce this; bun is uniquely strict. See https://github.com/oven-sh/bun/issues/8406. For both standalone and monorepo-root bun migrations, mirror the \`vite\` override as a top-level devDependency so bun's resolver sees a direct \`vite\` dep at install time. The override configured alongside still redirects the resolved package at vite-plus-core, so the user's actual import behavior is unchanged — they still get vite-plus-core for \`import 'vite'\`. The only snap.txt that needed updating is new-vite-monorepo-bun, which scaffolds a fresh bun monorepo without an existing \`vite\` dep at the root. migration-monorepo-bun and create-from-bun-monorepo-subdir already start with \`vite\` in devDeps and are unaffected. --- .../new-vite-monorepo-bun/snap.txt | 1 + packages/cli/src/migration/migrator.ts | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt b/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt index cb7003bc15..10a16780d5 100644 --- a/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt +++ b/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt @@ -26,6 +26,7 @@ vite.config.ts "prepare": "vp config" }, "devDependencies": { + "vite": "catalog:", "vite-plus": "catalog:" }, "overrides": { diff --git a/packages/cli/src/migration/migrator.ts b/packages/cli/src/migration/migrator.ts index 562f1c3424..06366f236f 100644 --- a/packages/cli/src/migration/migrator.ts +++ b/packages/cli/src/migration/migrator.ts @@ -921,6 +921,19 @@ export function rewriteStandaloneProject( ...pkg.overrides, ...VITE_PLUS_OVERRIDE_PACKAGES, }; + if (packageManager === PackageManager.bun) { + // Bun walks transitive peer-deps before resolving overrides; vitest + // 4.1.5 declares peer `vite ^6 || ^7 || ^8` and aborts with + // "vite@... failed to resolve" if `vite` isn't a direct dep somewhere + // in the tree, even when the override would redirect it. Mirror the + // override as a devDep so bun's resolver sees `vite` immediately; + // the override above still points it at vite-plus-core. + // See https://github.com/oven-sh/bun/issues/8406. + pkg.devDependencies = { + ...pkg.devDependencies, + vite: VITE_PLUS_OVERRIDE_PACKAGES.vite, + }; + } } else if (packageManager === PackageManager.pnpm) { // If package.json already has a "pnpm" field, keep using it; // otherwise use pnpm-workspace.yaml. @@ -1736,6 +1749,19 @@ function rewriteRootWorkspacePackageJson( }; } else if (packageManager === PackageManager.bun) { // bun overrides are handled in rewriteBunCatalog() with catalog: references + // Bun walks transitive peer-deps before resolving overrides; vitest 4.1.5 + // declares peer `vite ^6 || ^7 || ^8` and aborts unless `vite` is a direct + // dep at the workspace root. Mirror the override as a devDep; the override + // configured in rewriteBunCatalog still redirects it to vite-plus-core. + // See https://github.com/oven-sh/bun/issues/8406. + pkg.devDependencies = { + ...pkg.devDependencies, + vite: getCatalogDependencySpec( + pkg.devDependencies?.vite, + VITE_PLUS_OVERRIDE_PACKAGES.vite, + true, + ), + }; } else if (packageManager === PackageManager.pnpm) { const overrideKeys = Object.keys(VITE_PLUS_OVERRIDE_PACKAGES); if (isForceOverrideMode()) { From f46233fd32b6fd24a2851e01e4f6a708d262eba0 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 10:50:01 +0800 Subject: [PATCH 12/37] fix(ci): pack a vite-7.99.0.tgz alias so bun's name+version check passes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirroring the override target as a devDep wasn't enough — bun also validates that the resolved package's package.json#name matches the requested specifier. The file: target was @voidzero-dev/vite-plus-core, not vite, so bun still aborts with "vite@^6.0.0 || ^7.0.0 || ^8.0.0 failed to resolve" even after the devDep injection landed in 61289fb2c. Pack a second tgz with name=vite, version=7.99.0 (same code as core) and point VP_OVERRIDE_PACKAGES.vite at it. The user's package.json now gets: overrides.vite = file:.../vite-7.99.0.tgz (name=vite) overrides.@voidzero… = file:.../core-7.99.0.tgz (name=core) devDependencies.vite = file:.../vite-7.99.0.tgz (name=vite) which satisfies both of bun's checks; pnpm/npm/yarn don't care. Three pack steps now run sequentially: 1. set name=vite + version=7.99.0, pack core → vite-7.99.0.tgz 2. restore name=@voidzero-dev/vite-plus-core, pack core → voidzero-dev-vite-plus-core-7.99.0.tgz 3. pack cli (workspace:* → core@7.99.0 so install-global-cli matches) 4. git checkout the source package.json --- .github/workflows/e2e-test.yml | 35 +++++++++++++++++--------- .github/workflows/test-vp-create.yml | 37 ++++++++++++++++++---------- ecosystem-ci/patch-project.ts | 2 +- 3 files changed, 48 insertions(+), 26 deletions(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 18257eb67a..8133452ae5 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -108,18 +108,29 @@ jobs: - name: Pack packages into tgz run: | mkdir -p tmp/tgz - # Bun strictly validates the resolved package version against - # transitive peer constraints; vitest 4.1.5 declares peer - # `vite ^6 || ^7 || ^8` and bun aborts with "vite@^6.0.0 || ^7.0.0 - # || ^8.0.0 failed to resolve" when the override target's version - # is 0.0.0. pnpm/npm/yarn don't enforce this. See - # https://github.com/oven-sh/bun/issues/8406. Pack core with a - # synthetic version inside the satisfied range, then pack the CLI - # so its workspace:* dep on core resolves to that same version - # (otherwise install-global-cli can't find the right tgz). Restore - # the source package.json afterwards so the working tree stays at - # 0.0.0 for downstream steps. - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" + # Bun is uniquely strict about peer-dep resolution: + # 1. It checks the *resolved target's* package name and version + # against the peer range (vitest 4.1.5 declares peer + # `vite ^6 || ^7 || ^8`). + # 2. A file: override pointing at the vite-plus-core tgz fails + # both the name check (target is `@voidzero-dev/vite-plus-core` + # not `vite`) and the version check (0.0.0 is outside `^6|^7|^8`). + # pnpm/npm/yarn don't enforce either. See + # https://github.com/oven-sh/bun/issues/8406. + # + # Pack three tgz files: + # - vite-7.99.0.tgz: same code as core, but with name=vite, + # version=7.99.0. Used as the file: override target for `vite`. + # - voidzero-dev-vite-plus-core-7.99.0.tgz: real core package with + # version=7.99.0. Used as the file: override target for the + # scoped name + resolved by install-global-cli from the CLI's + # transitive @voidzero-dev/vite-plus-core@7.99.0 dep. + # - vite-plus-0.0.0.tgz: CLI; its workspace:* dep on core resolves + # to 7.99.0 because core/package.json was bumped before packing. + # Restore packages/core/package.json afterwards. + node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.name='vite';p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" + cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. + node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.name='@voidzero-dev/vite-plus-core';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. git checkout -- packages/core/package.json diff --git a/.github/workflows/test-vp-create.yml b/.github/workflows/test-vp-create.yml index e2d28c1976..a6f305b91f 100644 --- a/.github/workflows/test-vp-create.yml +++ b/.github/workflows/test-vp-create.yml @@ -93,18 +93,29 @@ jobs: - name: Pack packages into tgz run: | mkdir -p tmp/tgz - # Bun strictly validates the resolved package version against - # transitive peer constraints; vitest 4.1.5 declares peer - # `vite ^6 || ^7 || ^8` and bun aborts with "vite@^6.0.0 || ^7.0.0 - # || ^8.0.0 failed to resolve" when the override target's version - # is 0.0.0. pnpm/npm/yarn don't enforce this. See - # https://github.com/oven-sh/bun/issues/8406. Pack core with a - # synthetic version inside the satisfied range, then pack the CLI - # so its workspace:* dep on core resolves to that same version - # (otherwise install-global-cli can't find the right tgz). Restore - # the source package.json afterwards so the working tree stays at - # 0.0.0 for downstream steps. - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" + # Bun is uniquely strict about peer-dep resolution: + # 1. It checks the *resolved target's* package name and version + # against the peer range (vitest 4.1.5 declares peer + # `vite ^6 || ^7 || ^8`). + # 2. A file: override pointing at the vite-plus-core tgz fails + # both the name check (target is `@voidzero-dev/vite-plus-core` + # not `vite`) and the version check (0.0.0 is outside `^6|^7|^8`). + # pnpm/npm/yarn don't enforce either. See + # https://github.com/oven-sh/bun/issues/8406. + # + # Pack three tgz files: + # - vite-7.99.0.tgz: same code as core, but with name=vite, + # version=7.99.0. Used as the file: override target for `vite`. + # - voidzero-dev-vite-plus-core-7.99.0.tgz: real core package with + # version=7.99.0. Used as the file: override target for the + # scoped name + resolved by install-global-cli from the CLI's + # transitive @voidzero-dev/vite-plus-core@7.99.0 dep. + # - vite-plus-0.0.0.tgz: CLI; its workspace:* dep on core resolves + # to 7.99.0 because core/package.json was bumped before packing. + # Restore packages/core/package.json afterwards. + node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.name='vite';p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" + cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. + node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.name='@voidzero-dev/vite-plus-core';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. git checkout -- packages/core/package.json @@ -164,7 +175,7 @@ jobs: - yarn - bun env: - VP_OVERRIDE_PACKAGES: '{"vite":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-7.99.0.tgz","@voidzero-dev/vite-plus-core":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-7.99.0.tgz"}' + VP_OVERRIDE_PACKAGES: '{"vite":"file:${{ github.workspace }}/tmp/tgz/vite-7.99.0.tgz","@voidzero-dev/vite-plus-core":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-7.99.0.tgz"}' VP_VERSION: 'file:${{ github.workspace }}/tmp/tgz/vite-plus-0.0.0.tgz' # Force full dependency rewriting so the library template's existing # vite-plus dep gets overridden with the local tgz diff --git a/ecosystem-ci/patch-project.ts b/ecosystem-ci/patch-project.ts index 47320f13c9..6ad480fe6b 100644 --- a/ecosystem-ci/patch-project.ts +++ b/ecosystem-ci/patch-project.ts @@ -54,7 +54,7 @@ execSync(`${cli} migrate --no-agent --no-interactive`, { ...process.env, ...(forceFreshMigration ? { VP_FORCE_MIGRATE: '1' } : {}), VP_OVERRIDE_PACKAGES: JSON.stringify({ - vite: `file:${tgzDir}/voidzero-dev-vite-plus-core-7.99.0.tgz`, + vite: `file:${tgzDir}/vite-7.99.0.tgz`, '@voidzero-dev/vite-plus-core': `file:${tgzDir}/voidzero-dev-vite-plus-core-7.99.0.tgz`, }), VP_VERSION: `file:${tgzDir}/vite-plus-0.0.0.tgz`, From d3acd819422aa8e7005c425c49de9895720f0eef Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 11:12:36 +0800 Subject: [PATCH 13/37] fix(ci): post-process core tgz into vite alias instead of name-swapping during pack The previous masquerade approach renamed packages/core/package.json between two pnpm pack calls. Even with the name restored before packing the CLI, pnpm's workspace state was polluted: catalog `vite: workspace:@voidzero-dev/vite-plus-core@*` resolved to literal `vite@7.99.0` in the packed CLI manifest, and pnpm then failed at install time with `ERR_PNPM_NO_MATCHING_VERSION` looking up vite@7.99.0 in the npm registry. Pack core (version bumped to 7.99.0, name unchanged) and the CLI normally, then run a new `tool repack-vite-tgz` subcommand that reads the core tgz, rewrites the inner `package.json#name` to "vite", and writes a sibling `vite-7.99.0.tgz`. The repacked tgz still satisfies bun's strict name+version peer check for vitest 4.1.5's `peer vite ^6 || ^7 || ^8`, but no workspace pollution occurs because we never modify the in-tree package name. --- .github/workflows/e2e-test.yml | 18 ++++++++----- .github/workflows/test-vp-create.yml | 18 ++++++++----- packages/tools/package.json | 3 ++- packages/tools/src/index.ts | 6 ++++- packages/tools/src/repack-vite-tgz.ts | 38 +++++++++++++++++++++++++++ pnpm-lock.yaml | 3 +++ 6 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 packages/tools/src/repack-vite-tgz.ts diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 8133452ae5..1dfa5cc7c9 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -118,22 +118,26 @@ jobs: # pnpm/npm/yarn don't enforce either. See # https://github.com/oven-sh/bun/issues/8406. # - # Pack three tgz files: - # - vite-7.99.0.tgz: same code as core, but with name=vite, - # version=7.99.0. Used as the file: override target for `vite`. + # Produce three tgz files: # - voidzero-dev-vite-plus-core-7.99.0.tgz: real core package with # version=7.99.0. Used as the file: override target for the # scoped name + resolved by install-global-cli from the CLI's # transitive @voidzero-dev/vite-plus-core@7.99.0 dep. + # - vite-7.99.0.tgz: post-processed copy of the core tgz with + # `package.json#name` rewritten to "vite". Used as the file: + # override target for `vite` so bun's name+version check passes. # - vite-plus-0.0.0.tgz: CLI; its workspace:* dep on core resolves # to 7.99.0 because core/package.json was bumped before packing. - # Restore packages/core/package.json afterwards. - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.name='vite';p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" - cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.name='@voidzero-dev/vite-plus-core';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" + # We post-process the core tgz instead of name-swapping + # packages/core/package.json before pnpm pack: a temporary + # `name: "vite"` in the workspace pollutes catalog/workspace + # resolution when packing the CLI (pnpm rewrites `vite: catalog:` + # to literal `7.99.0`, which then fails to resolve at install time). + node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. git checkout -- packages/core/package.json + pnpm exec tool repack-vite-tgz tmp/tgz/voidzero-dev-vite-plus-core-7.99.0.tgz tmp/tgz/vite-7.99.0.tgz vite # Copy vp binary for e2e-test job (findVpBinary expects it in target/) cp target/${{ matrix.target }}/release/vp tmp/tgz/vp 2>/dev/null || cp target/${{ matrix.target }}/release/vp.exe tmp/tgz/vp.exe 2>/dev/null || true cp target/${{ matrix.target }}/release/vp-shim.exe tmp/tgz/vp-shim.exe 2>/dev/null || true diff --git a/.github/workflows/test-vp-create.yml b/.github/workflows/test-vp-create.yml index a6f305b91f..ffe1fa5f73 100644 --- a/.github/workflows/test-vp-create.yml +++ b/.github/workflows/test-vp-create.yml @@ -103,22 +103,26 @@ jobs: # pnpm/npm/yarn don't enforce either. See # https://github.com/oven-sh/bun/issues/8406. # - # Pack three tgz files: - # - vite-7.99.0.tgz: same code as core, but with name=vite, - # version=7.99.0. Used as the file: override target for `vite`. + # Produce three tgz files: # - voidzero-dev-vite-plus-core-7.99.0.tgz: real core package with # version=7.99.0. Used as the file: override target for the # scoped name + resolved by install-global-cli from the CLI's # transitive @voidzero-dev/vite-plus-core@7.99.0 dep. + # - vite-7.99.0.tgz: post-processed copy of the core tgz with + # `package.json#name` rewritten to "vite". Used as the file: + # override target for `vite` so bun's name+version check passes. # - vite-plus-0.0.0.tgz: CLI; its workspace:* dep on core resolves # to 7.99.0 because core/package.json was bumped before packing. - # Restore packages/core/package.json afterwards. - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.name='vite';p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" - cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.name='@voidzero-dev/vite-plus-core';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" + # We post-process the core tgz instead of name-swapping + # packages/core/package.json before pnpm pack: a temporary + # `name: "vite"` in the workspace pollutes catalog/workspace + # resolution when packing the CLI (pnpm rewrites `vite: catalog:` + # to literal `7.99.0`, which then fails to resolve at install time). + node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. git checkout -- packages/core/package.json + pnpm exec tool repack-vite-tgz tmp/tgz/voidzero-dev-vite-plus-core-7.99.0.tgz tmp/tgz/vite-7.99.0.tgz vite # Copy vp binary for test jobs cp target/x86_64-unknown-linux-gnu/release/vp tmp/tgz/vp ls -la tmp/tgz diff --git a/packages/tools/package.json b/packages/tools/package.json index a7751d531e..f9c7ae6d02 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -12,7 +12,8 @@ }, "dependencies": { "@yarnpkg/fslib": "catalog:", - "@yarnpkg/shell": "catalog:" + "@yarnpkg/shell": "catalog:", + "nanotar": "catalog:" }, "devDependencies": { "@oxc-node/cli": "catalog:", diff --git a/packages/tools/src/index.ts b/packages/tools/src/index.ts index 5a6fa9b58e..d8847ff5fa 100644 --- a/packages/tools/src/index.ts +++ b/packages/tools/src/index.ts @@ -29,10 +29,14 @@ switch (subcommand) { const { brandVite } = await import('./brand-vite.ts'); brandVite(); break; + case 'repack-vite-tgz': + const { repackViteTgz } = await import('./repack-vite-tgz.ts'); + await repackViteTgz(); + break; default: console.error(`Unknown subcommand: ${subcommand}`); console.error( - 'Available subcommands: snap-test, replace-file-content, sync-remote, json-sort, merge-peer-deps, install-global-cli, brand-vite', + 'Available subcommands: snap-test, replace-file-content, sync-remote, json-sort, merge-peer-deps, install-global-cli, brand-vite, repack-vite-tgz', ); process.exit(1); } diff --git a/packages/tools/src/repack-vite-tgz.ts b/packages/tools/src/repack-vite-tgz.ts new file mode 100644 index 0000000000..1cd3f7e783 --- /dev/null +++ b/packages/tools/src/repack-vite-tgz.ts @@ -0,0 +1,38 @@ +import { readFile, writeFile } from 'node:fs/promises'; + +import { createTarGzip, parseTarGzip, type TarFileInput } from 'nanotar'; + +export async function repackViteTgz() { + const [inputPath, outputPath, newName] = process.argv.slice(3); + + if (!inputPath || !outputPath || !newName) { + console.error('Usage: tool repack-vite-tgz '); + process.exit(1); + } + + const inputBytes = await readFile(inputPath); + const entries = await parseTarGzip(inputBytes); + + let patched = 0; + const repacked: TarFileInput[] = entries.map((entry) => { + let data = entry.data; + if (entry.name === 'package/package.json' && data) { + const pkg = JSON.parse(new TextDecoder().decode(data)) as Record; + pkg.name = newName; + data = new TextEncoder().encode(JSON.stringify(pkg, null, 2) + '\n'); + patched += 1; + } + return { name: entry.name, data, attrs: entry.attrs }; + }); + + if (patched !== 1) { + console.error(`Expected exactly one package/package.json entry, found ${patched}`); + process.exit(1); + } + + const outBytes = await createTarGzip(repacked); + await writeFile(outputPath, outBytes); + console.log( + `Repacked ${inputPath} -> ${outputPath} (name=${newName}, ${outBytes.byteLength} bytes)`, + ); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8af7905d35..c84e36c65c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -637,6 +637,9 @@ importers: '@yarnpkg/shell': specifier: 'catalog:' version: 4.1.3(typanion@3.14.0) + nanotar: + specifier: 'catalog:' + version: 0.3.0 devDependencies: '@oxc-node/cli': specifier: 'catalog:' From d9ddb9306a1febd195602d21752c670852f437cd Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 11:45:15 +0800 Subject: [PATCH 14/37] fix(ci): use core tgz for vite override except where bun is the target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pointing every package manager at the renamed vite-7.99.0.tgz worked around bun's strict peer check but broke pnpm: when both a workspace sub-package and the workspace override resolve to the same tgz that advertises itself as vite@7.99.0, pnpm tries to validate the version against the registry and aborts with ERR_PNPM_NO_MATCHING_VERSION. Revert to the main-branch shape for pnpm/npm/yarn (same core tgz for both `vite` and `@voidzero-dev/vite-plus-core` overrides) and keep the renamed tgz only for bun, where vitest's `peer vite ^6 || ^7 || ^8` demands a tgz whose package.json#name is "vite" and whose version is in range. Stop bumping core/CLI to 7.99.0 entirely; pack at 0.0.0 and post-process a sibling vite-7.99.0.tgz via `tool repack-vite-tgz`, which now also strips the workspace's vite→vite-plus-core self-ref so the alias tgz isn't circular. The test-vp-create matrix picks the override target per package manager via a new VITE_OVERRIDE_TGZ matrix env. ecosystem-ci/patch-project.ts mirrors that logic for the bun-vite-template project only; every other ecosystem project routes vite through the core tgz. --- .github/workflows/e2e-test.yml | 35 +++++++----------- .github/workflows/test-vp-create.yml | 46 ++++++++++++------------ ecosystem-ci/patch-project.ts | 16 +++++++-- packages/tools/src/repack-vite-tgz.ts | 51 ++++++++++++++++++++++++--- 4 files changed, 97 insertions(+), 51 deletions(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 1dfa5cc7c9..77a73cf9a5 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -108,36 +108,27 @@ jobs: - name: Pack packages into tgz run: | mkdir -p tmp/tgz + # Pack core and CLI normally (version stays at 0.0.0). + cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. + cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. # Bun is uniquely strict about peer-dep resolution: # 1. It checks the *resolved target's* package name and version # against the peer range (vitest 4.1.5 declares peer # `vite ^6 || ^7 || ^8`). # 2. A file: override pointing at the vite-plus-core tgz fails - # both the name check (target is `@voidzero-dev/vite-plus-core` + # both the name check (target is `@voidzero-dev/vite-plus-core`, # not `vite`) and the version check (0.0.0 is outside `^6|^7|^8`). - # pnpm/npm/yarn don't enforce either. See + # pnpm/npm/yarn don't enforce either, and using the same core tgz as + # the file: target for both `vite` and `@voidzero-dev/vite-plus-core` + # is the only configuration they install cleanly. See # https://github.com/oven-sh/bun/issues/8406. # - # Produce three tgz files: - # - voidzero-dev-vite-plus-core-7.99.0.tgz: real core package with - # version=7.99.0. Used as the file: override target for the - # scoped name + resolved by install-global-cli from the CLI's - # transitive @voidzero-dev/vite-plus-core@7.99.0 dep. - # - vite-7.99.0.tgz: post-processed copy of the core tgz with - # `package.json#name` rewritten to "vite". Used as the file: - # override target for `vite` so bun's name+version check passes. - # - vite-plus-0.0.0.tgz: CLI; its workspace:* dep on core resolves - # to 7.99.0 because core/package.json was bumped before packing. - # We post-process the core tgz instead of name-swapping - # packages/core/package.json before pnpm pack: a temporary - # `name: "vite"` in the workspace pollutes catalog/workspace - # resolution when packing the CLI (pnpm rewrites `vite: catalog:` - # to literal `7.99.0`, which then fails to resolve at install time). - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" - cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. - cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. - git checkout -- packages/core/package.json - pnpm exec tool repack-vite-tgz tmp/tgz/voidzero-dev-vite-plus-core-7.99.0.tgz tmp/tgz/vite-7.99.0.tgz vite + # Generate a sibling vite-7.99.0.tgz: a copy of the core tgz with + # `package.json#name` rewritten to "vite" and `version` to 7.99.0. + # ecosystem-ci/patch-project.ts points its vite override at this + # tgz only for bun-based projects (e.g. bun-vite-template); pnpm-, + # npm- and yarn-based ecosystem projects use the real core tgz. + pnpm exec tool repack-vite-tgz tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz tmp/tgz/vite-7.99.0.tgz vite 7.99.0 # Copy vp binary for e2e-test job (findVpBinary expects it in target/) cp target/${{ matrix.target }}/release/vp tmp/tgz/vp 2>/dev/null || cp target/${{ matrix.target }}/release/vp.exe tmp/tgz/vp.exe 2>/dev/null || true cp target/${{ matrix.target }}/release/vp-shim.exe tmp/tgz/vp-shim.exe 2>/dev/null || true diff --git a/.github/workflows/test-vp-create.yml b/.github/workflows/test-vp-create.yml index ffe1fa5f73..155438725f 100644 --- a/.github/workflows/test-vp-create.yml +++ b/.github/workflows/test-vp-create.yml @@ -93,36 +93,29 @@ jobs: - name: Pack packages into tgz run: | mkdir -p tmp/tgz + # Pack core and CLI normally (version stays at 0.0.0). + cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. + cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. # Bun is uniquely strict about peer-dep resolution: # 1. It checks the *resolved target's* package name and version # against the peer range (vitest 4.1.5 declares peer # `vite ^6 || ^7 || ^8`). # 2. A file: override pointing at the vite-plus-core tgz fails - # both the name check (target is `@voidzero-dev/vite-plus-core` + # both the name check (target is `@voidzero-dev/vite-plus-core`, # not `vite`) and the version check (0.0.0 is outside `^6|^7|^8`). - # pnpm/npm/yarn don't enforce either. See + # pnpm/npm/yarn don't enforce either, and using the same core tgz as + # the file: target for both `vite` and `@voidzero-dev/vite-plus-core` + # is the only configuration they install cleanly. See # https://github.com/oven-sh/bun/issues/8406. # - # Produce three tgz files: - # - voidzero-dev-vite-plus-core-7.99.0.tgz: real core package with - # version=7.99.0. Used as the file: override target for the - # scoped name + resolved by install-global-cli from the CLI's - # transitive @voidzero-dev/vite-plus-core@7.99.0 dep. - # - vite-7.99.0.tgz: post-processed copy of the core tgz with - # `package.json#name` rewritten to "vite". Used as the file: - # override target for `vite` so bun's name+version check passes. - # - vite-plus-0.0.0.tgz: CLI; its workspace:* dep on core resolves - # to 7.99.0 because core/package.json was bumped before packing. - # We post-process the core tgz instead of name-swapping - # packages/core/package.json before pnpm pack: a temporary - # `name: "vite"` in the workspace pollutes catalog/workspace - # resolution when packing the CLI (pnpm rewrites `vite: catalog:` - # to literal `7.99.0`, which then fails to resolve at install time). - node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('packages/core/package.json','utf8'));p.version='7.99.0';fs.writeFileSync('packages/core/package.json',JSON.stringify(p,null,2)+'\n')" - cd packages/core && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. - cd packages/cli && pnpm pack --pack-destination ../../tmp/tgz && cd ../.. - git checkout -- packages/core/package.json - pnpm exec tool repack-vite-tgz tmp/tgz/voidzero-dev-vite-plus-core-7.99.0.tgz tmp/tgz/vite-7.99.0.tgz vite + # Generate a sibling vite-7.99.0.tgz: a copy of the core tgz with + # `package.json#name` rewritten to "vite" and `version` to 7.99.0. + # Only the bun matrix entry below points its vite override at this + # alias tgz; pnpm/npm/yarn keep pointing at the real core tgz so + # pnpm's workspace resolver doesn't trip on a "vite@" + # registry lookup (the renamed tgz makes pnpm register the dep as + # vite@7.99.0 and then probe npmjs.org to validate the version). + pnpm exec tool repack-vite-tgz tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz tmp/tgz/vite-7.99.0.tgz vite 7.99.0 # Copy vp binary for test jobs cp target/x86_64-unknown-linux-gnu/release/vp tmp/tgz/vp ls -la tmp/tgz @@ -179,7 +172,12 @@ jobs: - yarn - bun env: - VP_OVERRIDE_PACKAGES: '{"vite":"file:${{ github.workspace }}/tmp/tgz/vite-7.99.0.tgz","@voidzero-dev/vite-plus-core":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-7.99.0.tgz"}' + # Bun's strict peer check requires the `vite` override target's tgz to be + # named "vite" with a version satisfying vitest's `peer vite ^6 || ^7 || ^8`. + # The bun matrix entry uses the masquerade tgz (vite-7.99.0.tgz). pnpm/npm/yarn + # point at the real core tgz — anything else trips a registry lookup for + # vite@ when sub-package and override targets are both file: tgz aliases. + VITE_OVERRIDE_TGZ: ${{ matrix.package-manager == 'bun' && 'vite-7.99.0.tgz' || 'voidzero-dev-vite-plus-core-0.0.0.tgz' }} VP_VERSION: 'file:${{ github.workspace }}/tmp/tgz/vite-plus-0.0.0.tgz' # Force full dependency rewriting so the library template's existing # vite-plus dep gets overridden with the local tgz @@ -212,6 +210,8 @@ jobs: - name: Run vp create ${{ matrix.template.name }} with ${{ matrix.package-manager }} working-directory: ${{ runner.temp }} + env: + VP_OVERRIDE_PACKAGES: '{"vite":"file:${{ github.workspace }}/tmp/tgz/${{ env.VITE_OVERRIDE_TGZ }}","@voidzero-dev/vite-plus-core":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz"}' run: | vp create ${{ matrix.template.create-args }} \ --no-interactive \ diff --git a/ecosystem-ci/patch-project.ts b/ecosystem-ci/patch-project.ts index 6ad480fe6b..7e7c83889b 100644 --- a/ecosystem-ci/patch-project.ts +++ b/ecosystem-ci/patch-project.ts @@ -47,6 +47,18 @@ if (project === 'vinext') { // vp migrate runs full dependency rewriting instead of skipping. const forceFreshMigration = 'forceFreshMigration' in repoConfig && repoConfig.forceFreshMigration; +// Bun is uniquely strict about vitest's `peer vite ^6 || ^7 || ^8` resolution +// (https://github.com/oven-sh/bun/issues/8406): it checks both the override +// target's package name and version. Point bun-based projects at the +// vite-7.99.0 alias tgz (a copy of core renamed to "vite" with a satisfying +// version); pnpm/npm/yarn must keep pointing at the real core tgz, otherwise +// they trip a registry lookup for "vite@" when a workspace +// sub-package and the override both reference the same vite-named alias. +const isBunProject = project === 'bun-vite-template'; +const viteOverrideTgz = isBunProject + ? `vite-7.99.0.tgz` + : `voidzero-dev-vite-plus-core-0.0.0.tgz`; + execSync(`${cli} migrate --no-agent --no-interactive`, { cwd, stdio: 'inherit', @@ -54,8 +66,8 @@ execSync(`${cli} migrate --no-agent --no-interactive`, { ...process.env, ...(forceFreshMigration ? { VP_FORCE_MIGRATE: '1' } : {}), VP_OVERRIDE_PACKAGES: JSON.stringify({ - vite: `file:${tgzDir}/vite-7.99.0.tgz`, - '@voidzero-dev/vite-plus-core': `file:${tgzDir}/voidzero-dev-vite-plus-core-7.99.0.tgz`, + vite: `file:${tgzDir}/${viteOverrideTgz}`, + '@voidzero-dev/vite-plus-core': `file:${tgzDir}/voidzero-dev-vite-plus-core-0.0.0.tgz`, }), VP_VERSION: `file:${tgzDir}/vite-plus-0.0.0.tgz`, }, diff --git a/packages/tools/src/repack-vite-tgz.ts b/packages/tools/src/repack-vite-tgz.ts index 1cd3f7e783..45edf14ca3 100644 --- a/packages/tools/src/repack-vite-tgz.ts +++ b/packages/tools/src/repack-vite-tgz.ts @@ -2,11 +2,43 @@ import { readFile, writeFile } from 'node:fs/promises'; import { createTarGzip, parseTarGzip, type TarFileInput } from 'nanotar'; +interface PackageJson { + name?: string; + version?: string; + dependencies?: Record; + devDependencies?: Record; + peerDependencies?: Record; + optionalDependencies?: Record; +} + +function stripVitePlusCoreSelfRefs(pkg: PackageJson, newName: string): void { + for (const field of [ + 'dependencies', + 'devDependencies', + 'peerDependencies', + 'optionalDependencies', + ] as const) { + const group = pkg[field]; + if (!group) continue; + for (const [key, value] of Object.entries(group)) { + if ( + (key === newName || key === '@voidzero-dev/vite-plus-core') && + typeof value === 'string' && + value.includes('@voidzero-dev/vite-plus-core') + ) { + delete group[key]; + } + } + } +} + export async function repackViteTgz() { - const [inputPath, outputPath, newName] = process.argv.slice(3); + const [inputPath, outputPath, newName, newVersion] = process.argv.slice(3); if (!inputPath || !outputPath || !newName) { - console.error('Usage: tool repack-vite-tgz '); + console.error( + 'Usage: tool repack-vite-tgz [new-version]', + ); process.exit(1); } @@ -17,8 +49,17 @@ export async function repackViteTgz() { const repacked: TarFileInput[] = entries.map((entry) => { let data = entry.data; if (entry.name === 'package/package.json' && data) { - const pkg = JSON.parse(new TextDecoder().decode(data)) as Record; + const pkg = JSON.parse(new TextDecoder().decode(data)) as PackageJson; pkg.name = newName; + if (newVersion) { + pkg.version = newVersion; + } + // Strip any self-ref (`vite: npm:@voidzero-dev/vite-plus-core@...`) + // injected by the workspace-level vite -> vite-plus-core override at + // pnpm pack time. Once we rename the tgz to "vite", this becomes a + // circular self-dependency that confuses pnpm's resolver and triggers a + // registry lookup for the alias target version. + stripVitePlusCoreSelfRefs(pkg, newName); data = new TextEncoder().encode(JSON.stringify(pkg, null, 2) + '\n'); patched += 1; } @@ -33,6 +74,8 @@ export async function repackViteTgz() { const outBytes = await createTarGzip(repacked); await writeFile(outputPath, outBytes); console.log( - `Repacked ${inputPath} -> ${outputPath} (name=${newName}, ${outBytes.byteLength} bytes)`, + `Repacked ${inputPath} -> ${outputPath} (name=${newName}${ + newVersion ? `, version=${newVersion}` : '' + }, ${outBytes.byteLength} bytes)`, ); } From b95f98c71331314a56be390ea95e8e3a6cab3f9c Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 11:50:14 +0800 Subject: [PATCH 15/37] chore: vp check --fix Apply formatting fixes flagged by `vp check`: oxfmt added braces around single-line if-bodies in build.ts and reflowed the new repack-script helper and ecosystem-ci patch ternary. No behavior change. --- ecosystem-ci/patch-project.ts | 4 +--- packages/cli/build.ts | 12 +++++++++--- packages/tools/src/repack-vite-tgz.ts | 8 ++++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/ecosystem-ci/patch-project.ts b/ecosystem-ci/patch-project.ts index 7e7c83889b..f9e44eac62 100644 --- a/ecosystem-ci/patch-project.ts +++ b/ecosystem-ci/patch-project.ts @@ -55,9 +55,7 @@ const forceFreshMigration = 'forceFreshMigration' in repoConfig && repoConfig.fo // they trip a registry lookup for "vite@" when a workspace // sub-package and the override both reference the same vite-named alias. const isBunProject = project === 'bun-vite-template'; -const viteOverrideTgz = isBunProject - ? `vite-7.99.0.tgz` - : `voidzero-dev-vite-plus-core-0.0.0.tgz`; +const viteOverrideTgz = isBunProject ? `vite-7.99.0.tgz` : `voidzero-dev-vite-plus-core-0.0.0.tgz`; execSync(`${cli} migrate --no-agent --no-interactive`, { cwd, diff --git a/packages/cli/build.ts b/packages/cli/build.ts index 4f01808273..617fb1643d 100644 --- a/packages/cli/build.ts +++ b/packages/cli/build.ts @@ -642,15 +642,21 @@ function resolveUpstreamDtsPath( } const value = exportValue as Record; if (condition === 'types') { - if (typeof value.types === 'string') return join(providerPkgRoot, value.types); + if (typeof value.types === 'string') { + return join(providerPkgRoot, value.types); + } if (typeof value.import === 'object' && value.import !== null) { const types = (value.import as Record).types; - if (typeof types === 'string') return join(providerPkgRoot, types); + if (typeof types === 'string') { + return join(providerPkgRoot, types); + } } } else { if (typeof value.require === 'object' && value.require !== null) { const types = (value.require as Record).types; - if (typeof types === 'string') return join(providerPkgRoot, types); + if (typeof types === 'string') { + return join(providerPkgRoot, types); + } } } return null; diff --git a/packages/tools/src/repack-vite-tgz.ts b/packages/tools/src/repack-vite-tgz.ts index 45edf14ca3..c97cdf07e5 100644 --- a/packages/tools/src/repack-vite-tgz.ts +++ b/packages/tools/src/repack-vite-tgz.ts @@ -19,7 +19,9 @@ function stripVitePlusCoreSelfRefs(pkg: PackageJson, newName: string): void { 'optionalDependencies', ] as const) { const group = pkg[field]; - if (!group) continue; + if (!group) { + continue; + } for (const [key, value] of Object.entries(group)) { if ( (key === newName || key === '@voidzero-dev/vite-plus-core') && @@ -36,9 +38,7 @@ export async function repackViteTgz() { const [inputPath, outputPath, newName, newVersion] = process.argv.slice(3); if (!inputPath || !outputPath || !newName) { - console.error( - 'Usage: tool repack-vite-tgz [new-version]', - ); + console.error('Usage: tool repack-vite-tgz [new-version]'); process.exit(1); } From 5cf3a372823ca07b9dd94917738ad389f37d7e16 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 13:29:34 +0800 Subject: [PATCH 16/37] fix(migration): override vitest + @vitest/* family to single version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restores deduping previously done by the bundled wrapper. Without this, downstream projects co-resolve their own vitest with the one vp-cli ships, causing undefined `describe` (dual runner state) and TS2769 type clashes. Pinned to VITEST_VERSION (4.1.5) — the version vp-cli ships transitively. ecosystem-ci/patch-project.ts mirrors the same overrides so the CI matrix exercises the same dedup behavior production users get. Co-Authored-By: Claude Opus 4.7 --- ecosystem-ci/patch-project.ts | 14 +++ .../snap.txt | 1 + .../migration-add-git-hooks/snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../migration-baseurl-tsconfig/snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../migration-composed-husky-prepare/snap.txt | 32 +++++++ .../migration-env-prefix-lint-staged/snap.txt | 32 +++++++ .../migration-eslint-lint-staged/snap.txt | 32 +++++++ .../migration-eslint-lintstagedrc/snap.txt | 32 +++++++ .../migration-eslint-npx-wrapper/snap.txt | 32 +++++++ .../migration-eslint/snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../migration-existing-husky/snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../migration-from-tsdown/snap.txt | 32 +++++++ .../migration-from-vitest-config/snap.txt | 34 ++++++- .../migration-from-vitest-files/snap.txt | 34 ++++++- .../snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../migration-husky-latest-dist-tag/snap.txt | 32 +++++++ .../migration-husky-or-prepare/snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../migration-lint-staged-in-scripts/snap.txt | 32 +++++++ .../migration-lint-staged-merge-fail/snap.txt | 32 +++++++ .../migration-lint-staged-ts-config/snap.txt | 32 +++++++ .../migration-lintstagedrc-json/snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../migration-merge-vite-config-js/snap.txt | 32 +++++++ .../migration-merge-vite-config-ts/snap.txt | 34 ++++++- .../migration-monorepo-bun/snap.txt | 21 ++++- .../snap.txt | 32 +++++++ .../migration-monorepo-pnpm/snap.txt | 34 ++++++- .../migration-monorepo-yarn4/snap.txt | 18 +++- .../migration-no-git-repo/snap.txt | 32 +++++++ .../migration-no-hooks-with-husky/snap.txt | 32 +++++++ .../migration-no-hooks/snap.txt | 32 +++++++ .../migration-other-hook-tool/snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../migration-oxlintrc-jsonc/snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../migration-prettier-eslint-combo/snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../migration-prettier-lint-staged/snap.txt | 32 +++++++ .../migration-prettier-pkg-json/snap.txt | 32 +++++++ .../migration-prettier/snap.txt | 32 +++++++ .../migration-rewrite-declare-module/snap.txt | 32 +++++++ .../migration-skip-vite-dependency/snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../migration-standalone-npm/snap.txt | 12 ++- .../migration-standalone-pnpm/snap.txt | 34 ++++++- .../migration-subpath/snap.txt | 32 +++++++ .../snap.txt | 32 +++++++ .../migration-vite-version/snap.txt | 32 +++++++ .../migration-vitest-peer-dep/snap.txt | 32 +++++++ .../new-vite-monorepo-bun/snap.txt | 18 +++- .../new-vite-monorepo/snap.txt | 32 +++++++ .../create-org-bundled-monorepo/snap.txt | 32 +++++++ .../src/migration/__tests__/migrator.spec.ts | 89 +++++++++++-------- packages/cli/src/migration/migrator.ts | 9 +- packages/cli/src/utils/constants.ts | 10 +++ 70 files changed, 2103 insertions(+), 51 deletions(-) diff --git a/ecosystem-ci/patch-project.ts b/ecosystem-ci/patch-project.ts index f9e44eac62..8c85e033dd 100644 --- a/ecosystem-ci/patch-project.ts +++ b/ecosystem-ci/patch-project.ts @@ -57,6 +57,19 @@ const forceFreshMigration = 'forceFreshMigration' in repoConfig && repoConfig.fo const isBunProject = project === 'bun-vite-template'; const viteOverrideTgz = isBunProject ? `vite-7.99.0.tgz` : `voidzero-dev-vite-plus-core-0.0.0.tgz`; +// Keep in sync with VITEST_VERSION in packages/cli/src/utils/constants.ts. +const VITEST_VERSION = '4.1.5'; +const vitestOverrides = { + vitest: VITEST_VERSION, + '@vitest/expect': VITEST_VERSION, + '@vitest/runner': VITEST_VERSION, + '@vitest/snapshot': VITEST_VERSION, + '@vitest/spy': VITEST_VERSION, + '@vitest/utils': VITEST_VERSION, + '@vitest/mocker': VITEST_VERSION, + '@vitest/pretty-format': VITEST_VERSION, +}; + execSync(`${cli} migrate --no-agent --no-interactive`, { cwd, stdio: 'inherit', @@ -66,6 +79,7 @@ execSync(`${cli} migrate --no-agent --no-interactive`, { VP_OVERRIDE_PACKAGES: JSON.stringify({ vite: `file:${tgzDir}/${viteOverrideTgz}`, '@voidzero-dev/vite-plus-core': `file:${tgzDir}/voidzero-dev-vite-plus-core-0.0.0.tgz`, + ...vitestOverrides, }), VP_VERSION: `file:${tgzDir}/vite-plus-0.0.0.tgz`, }, diff --git a/packages/cli/snap-tests-global/command-add-pnpm11-with-workspace/snap.txt b/packages/cli/snap-tests-global/command-add-pnpm11-with-workspace/snap.txt index 6e882943ac..6bd8bbb3c2 100644 --- a/packages/cli/snap-tests-global/command-add-pnpm11-with-workspace/snap.txt +++ b/packages/cli/snap-tests-global/command-add-pnpm11-with-workspace/snap.txt @@ -93,6 +93,7 @@ Done in ms using pnpm v } > vp add -E testnpm2 test-vite-plus-install --filter "*" && cat package.json packages/app/package.json packages/utils/package.json # should add testnpm2 test-vite-plus-install to all packages except workspace root +[WARN] GET https://registry./testnpm2 error (ECONNRESET). Will retry in 10 seconds. 2 retries left. Progress: resolved , reused , downloaded , added , done Done in ms using pnpm v { diff --git a/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt b/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt index 0d9643f560..4ce77e95a1 100644 --- a/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt @@ -21,14 +21,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat .vite-hooks/pre-commit # check pre-commit hook vp staged diff --git a/packages/cli/snap-tests-global/migration-auto-create-vite-config/snap.txt b/packages/cli/snap-tests-global/migration-auto-create-vite-config/snap.txt index 79173673fa..18f8b6437e 100644 --- a/packages/cli/snap-tests-global/migration-auto-create-vite-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-auto-create-vite-config/snap.txt @@ -51,11 +51,43 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-baseurl-tsconfig/snap.txt b/packages/cli/snap-tests-global/migration-baseurl-tsconfig/snap.txt index 37ffa0d8a2..fca4177b80 100644 --- a/packages/cli/snap-tests-global/migration-baseurl-tsconfig/snap.txt +++ b/packages/cli/snap-tests-global/migration-baseurl-tsconfig/snap.txt @@ -44,11 +44,43 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-chained-lint-staged-pre-commit/snap.txt b/packages/cli/snap-tests-global/migration-chained-lint-staged-pre-commit/snap.txt index 36d6c12f9e..a17217d5d2 100644 --- a/packages/cli/snap-tests-global/migration-chained-lint-staged-pre-commit/snap.txt +++ b/packages/cli/snap-tests-global/migration-chained-lint-staged-pre-commit/snap.txt @@ -21,14 +21,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt b/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt index 9e82198b08..be31c8cb64 100644 --- a/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt +++ b/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt @@ -21,14 +21,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat .config/husky/pre-commit # pre-commit hook should be in custom dir vp staged diff --git a/packages/cli/snap-tests-global/migration-composed-husky-prepare/snap.txt b/packages/cli/snap-tests-global/migration-composed-husky-prepare/snap.txt index a984ee4628..b39bd11c8b 100644 --- a/packages/cli/snap-tests-global/migration-composed-husky-prepare/snap.txt +++ b/packages/cli/snap-tests-global/migration-composed-husky-prepare/snap.txt @@ -21,11 +21,43 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-env-prefix-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-env-prefix-lint-staged/snap.txt index fe31dc1fb8..d5813a49c0 100644 --- a/packages/cli/snap-tests-global/migration-env-prefix-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-env-prefix-lint-staged/snap.txt @@ -21,14 +21,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-eslint-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-eslint-lint-staged/snap.txt index 49a3c5cf45..2303b04524 100644 --- a/packages/cli/snap-tests-global/migration-eslint-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-eslint-lint-staged/snap.txt @@ -21,14 +21,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat vite.config.ts # check oxlint config and staged config merged into vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-eslint-lintstagedrc/snap.txt b/packages/cli/snap-tests-global/migration-eslint-lintstagedrc/snap.txt index 139ee5c82d..497e2a08c2 100644 --- a/packages/cli/snap-tests-global/migration-eslint-lintstagedrc/snap.txt +++ b/packages/cli/snap-tests-global/migration-eslint-lintstagedrc/snap.txt @@ -21,14 +21,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > test ! -f .lintstagedrc.json # check lintstagedrc.json is removed > cat vite.config.ts # check oxlint config merged into vite.config.ts diff --git a/packages/cli/snap-tests-global/migration-eslint-npx-wrapper/snap.txt b/packages/cli/snap-tests-global/migration-eslint-npx-wrapper/snap.txt index 92fde94658..3664be6ff3 100644 --- a/packages/cli/snap-tests-global/migration-eslint-npx-wrapper/snap.txt +++ b/packages/cli/snap-tests-global/migration-eslint-npx-wrapper/snap.txt @@ -26,13 +26,45 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > test ! -f eslint.config.mjs # check eslint config is removed \ No newline at end of file diff --git a/packages/cli/snap-tests-global/migration-eslint/snap.txt b/packages/cli/snap-tests-global/migration-eslint/snap.txt index 5a00331f20..0b9f35fdb4 100644 --- a/packages/cli/snap-tests-global/migration-eslint/snap.txt +++ b/packages/cli/snap-tests-global/migration-eslint/snap.txt @@ -24,14 +24,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > test ! -f eslint.config.mjs # check eslint config is removed > cat vite.config.ts # check oxlint config merged into vite.config.ts diff --git a/packages/cli/snap-tests-global/migration-existing-husky-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-existing-husky-lint-staged/snap.txt index c29eb91e22..5cedf9a5a0 100644 --- a/packages/cli/snap-tests-global/migration-existing-husky-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-husky-lint-staged/snap.txt @@ -21,14 +21,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-existing-husky-v8-hooks/snap.txt b/packages/cli/snap-tests-global/migration-existing-husky-v8-hooks/snap.txt index c625deb5d5..5579ee2e03 100644 --- a/packages/cli/snap-tests-global/migration-existing-husky-v8-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-husky-v8-hooks/snap.txt @@ -24,14 +24,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat .husky/pre-commit # hook file should be unchanged (still has bootstrap) . "$(dirname -- "$0")/_/husky.sh" diff --git a/packages/cli/snap-tests-global/migration-existing-husky-v8-multi-hooks/snap.txt b/packages/cli/snap-tests-global/migration-existing-husky-v8-multi-hooks/snap.txt index dff5aecefc..3c372f31d2 100644 --- a/packages/cli/snap-tests-global/migration-existing-husky-v8-multi-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-husky-v8-multi-hooks/snap.txt @@ -24,14 +24,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat .husky/pre-commit # hook file should be unchanged (still has bootstrap) . "$(dirname -- "$0")/_/husky.sh" diff --git a/packages/cli/snap-tests-global/migration-existing-husky/snap.txt b/packages/cli/snap-tests-global/migration-existing-husky/snap.txt index 1bd95c9a83..7426c9a704 100644 --- a/packages/cli/snap-tests-global/migration-existing-husky/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-husky/snap.txt @@ -21,14 +21,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat .vite-hooks/pre-commit # check pre-commit hook rewritten to vp staged vp staged diff --git a/packages/cli/snap-tests-global/migration-existing-lint-staged-config/snap.txt b/packages/cli/snap-tests-global/migration-existing-lint-staged-config/snap.txt index 7798f51a5c..1993658615 100644 --- a/packages/cli/snap-tests-global/migration-existing-lint-staged-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-lint-staged-config/snap.txt @@ -21,14 +21,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > test ! -f .lintstagedrc.json # check lintstagedrc.json (should be deleted after inlining to vite.config.ts) > cat vite.config.ts # check staged config migrated to vite.config.ts diff --git a/packages/cli/snap-tests-global/migration-existing-pnpm-exec-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-existing-pnpm-exec-lint-staged/snap.txt index 0eb55dd9ed..b4d996f03b 100644 --- a/packages/cli/snap-tests-global/migration-existing-pnpm-exec-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-pnpm-exec-lint-staged/snap.txt @@ -21,14 +21,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-existing-prepare-script/snap.txt b/packages/cli/snap-tests-global/migration-existing-prepare-script/snap.txt index 1ebbe16262..9f62ab7d36 100644 --- a/packages/cli/snap-tests-global/migration-existing-prepare-script/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-prepare-script/snap.txt @@ -22,14 +22,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat .vite-hooks/pre-commit # check pre-commit hook vp staged diff --git a/packages/cli/snap-tests-global/migration-from-tsdown-json-config/snap.txt b/packages/cli/snap-tests-global/migration-from-tsdown-json-config/snap.txt index 4690b8400a..02968f1686 100644 --- a/packages/cli/snap-tests-global/migration-from-tsdown-json-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-tsdown-json-config/snap.txt @@ -46,14 +46,46 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > vp migrate --no-interactive # run migration again to check if it is idempotent This project is already using Vite+! Happy coding! diff --git a/packages/cli/snap-tests-global/migration-from-tsdown/snap.txt b/packages/cli/snap-tests-global/migration-from-tsdown/snap.txt index 87f3ea24de..67c649f122 100644 --- a/packages/cli/snap-tests-global/migration-from-tsdown/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-tsdown/snap.txt @@ -48,14 +48,46 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > vp migrate --no-interactive # run migration again to check if it is idempotent This project is already using Vite+! Happy coding! diff --git a/packages/cli/snap-tests-global/migration-from-vitest-config/snap.txt b/packages/cli/snap-tests-global/migration-from-vitest-config/snap.txt index 5f2b83d5d1..fc0d2d0201 100644 --- a/packages/cli/snap-tests-global/migration-from-vitest-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-vitest-config/snap.txt @@ -41,7 +41,7 @@ export default defineConfig({ }, "devDependencies": { "vite": "catalog:", - "vitest": "^4.0.0", + "vitest": "catalog:", "playwright": "*", "vite-plus": "catalog:" }, @@ -51,11 +51,43 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt b/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt index b934c5d0d3..a416b1a6b2 100644 --- a/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt @@ -16,7 +16,7 @@ }, "devDependencies": { "vite": "catalog:", - "vitest": "^4.0.0", + "vitest": "catalog:", "playwright": "*", "vite-plus": "catalog:" }, @@ -26,14 +26,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat test/hello.ts # check test/hello.ts import { server } from 'vite-plus/test/browser-playwright/context'; diff --git a/packages/cli/snap-tests-global/migration-hooks-skip-on-existing-hookspath/snap.txt b/packages/cli/snap-tests-global/migration-hooks-skip-on-existing-hookspath/snap.txt index 47331d89bc..5e1f59ac47 100644 --- a/packages/cli/snap-tests-global/migration-hooks-skip-on-existing-hookspath/snap.txt +++ b/packages/cli/snap-tests-global/migration-hooks-skip-on-existing-hookspath/snap.txt @@ -24,14 +24,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > git config --local core.hooksPath # should still be .custom-hooks .custom-hooks diff --git a/packages/cli/snap-tests-global/migration-husky-latest-dist-tag-v9-installed/snap.txt b/packages/cli/snap-tests-global/migration-husky-latest-dist-tag-v9-installed/snap.txt index f58a4409d3..b7d4ba2e63 100644 --- a/packages/cli/snap-tests-global/migration-husky-latest-dist-tag-v9-installed/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-latest-dist-tag-v9-installed/snap.txt @@ -21,11 +21,43 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-husky-latest-dist-tag/snap.txt b/packages/cli/snap-tests-global/migration-husky-latest-dist-tag/snap.txt index 93f1f3a31c..cfe0fdc9b5 100644 --- a/packages/cli/snap-tests-global/migration-husky-latest-dist-tag/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-latest-dist-tag/snap.txt @@ -23,11 +23,43 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-husky-or-prepare/snap.txt b/packages/cli/snap-tests-global/migration-husky-or-prepare/snap.txt index b24875fd8c..c7b648d8ce 100644 --- a/packages/cli/snap-tests-global/migration-husky-or-prepare/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-or-prepare/snap.txt @@ -21,11 +21,43 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-husky-semicolon-prepare/snap.txt b/packages/cli/snap-tests-global/migration-husky-semicolon-prepare/snap.txt index 0e612095b7..6a5361aa75 100644 --- a/packages/cli/snap-tests-global/migration-husky-semicolon-prepare/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-semicolon-prepare/snap.txt @@ -21,11 +21,43 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-husky-v8-preserves-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-husky-v8-preserves-lint-staged/snap.txt index 96986e2b14..aa7f9631f9 100644 --- a/packages/cli/snap-tests-global/migration-husky-v8-preserves-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-v8-preserves-lint-staged/snap.txt @@ -27,11 +27,43 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-lint-staged-in-scripts/snap.txt b/packages/cli/snap-tests-global/migration-lint-staged-in-scripts/snap.txt index 221633b129..24b70595ad 100644 --- a/packages/cli/snap-tests-global/migration-lint-staged-in-scripts/snap.txt +++ b/packages/cli/snap-tests-global/migration-lint-staged-in-scripts/snap.txt @@ -22,14 +22,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-lint-staged-merge-fail/snap.txt b/packages/cli/snap-tests-global/migration-lint-staged-merge-fail/snap.txt index b899c09edc..86f1c47acf 100644 --- a/packages/cli/snap-tests-global/migration-lint-staged-merge-fail/snap.txt +++ b/packages/cli/snap-tests-global/migration-lint-staged-merge-fail/snap.txt @@ -30,14 +30,46 @@ Please add staged config to vite.config.ts manually, see https://viteplus.dev/gu > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat vite.config.ts # vite config should be unchanged (merge failed) const config = { plugins: [] }; diff --git a/packages/cli/snap-tests-global/migration-lint-staged-ts-config/snap.txt b/packages/cli/snap-tests-global/migration-lint-staged-ts-config/snap.txt index 8084759590..2680b69695 100644 --- a/packages/cli/snap-tests-global/migration-lint-staged-ts-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-lint-staged-ts-config/snap.txt @@ -25,14 +25,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat lint-staged.config.ts # check TS config is not modified export default { diff --git a/packages/cli/snap-tests-global/migration-lintstagedrc-json/snap.txt b/packages/cli/snap-tests-global/migration-lintstagedrc-json/snap.txt index 03e14d64d2..2391a2b7dc 100644 --- a/packages/cli/snap-tests-global/migration-lintstagedrc-json/snap.txt +++ b/packages/cli/snap-tests-global/migration-lintstagedrc-json/snap.txt @@ -93,14 +93,46 @@ Documentation: https://viteplus.dev/guide/migrate > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-lintstagedrc-merge-fail/snap.txt b/packages/cli/snap-tests-global/migration-lintstagedrc-merge-fail/snap.txt index becb210241..599bd04ca2 100644 --- a/packages/cli/snap-tests-global/migration-lintstagedrc-merge-fail/snap.txt +++ b/packages/cli/snap-tests-global/migration-lintstagedrc-merge-fail/snap.txt @@ -27,14 +27,46 @@ Please add staged config to vite.config.ts manually, see https://viteplus.dev/gu > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat .lintstagedrc.json # config file should be preserved when merge fails { diff --git a/packages/cli/snap-tests-global/migration-lintstagedrc-not-support/snap.txt b/packages/cli/snap-tests-global/migration-lintstagedrc-not-support/snap.txt index 10eec58cc3..796b4958dc 100644 --- a/packages/cli/snap-tests-global/migration-lintstagedrc-not-support/snap.txt +++ b/packages/cli/snap-tests-global/migration-lintstagedrc-not-support/snap.txt @@ -38,11 +38,43 @@ export default { > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-lintstagedrc-staged-exists/snap.txt b/packages/cli/snap-tests-global/migration-lintstagedrc-staged-exists/snap.txt index e5f88903c8..ffa874eb58 100644 --- a/packages/cli/snap-tests-global/migration-lintstagedrc-staged-exists/snap.txt +++ b/packages/cli/snap-tests-global/migration-lintstagedrc-staged-exists/snap.txt @@ -22,14 +22,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > test -f .lintstagedrc.json && echo 'lintstagedrc.json still exists' || echo 'lintstagedrc.json was deleted' # should still exist lintstagedrc.json still exists diff --git a/packages/cli/snap-tests-global/migration-merge-vite-config-js/snap.txt b/packages/cli/snap-tests-global/migration-merge-vite-config-js/snap.txt index 8c69853ed1..32d1a7a32a 100644 --- a/packages/cli/snap-tests-global/migration-merge-vite-config-js/snap.txt +++ b/packages/cli/snap-tests-global/migration-merge-vite-config-js/snap.txt @@ -50,11 +50,43 @@ export default { > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-merge-vite-config-ts/snap.txt b/packages/cli/snap-tests-global/migration-merge-vite-config-ts/snap.txt index 54c3ab4c81..c7143d6230 100644 --- a/packages/cli/snap-tests-global/migration-merge-vite-config-ts/snap.txt +++ b/packages/cli/snap-tests-global/migration-merge-vite-config-ts/snap.txt @@ -74,7 +74,7 @@ export default defineConfig({ "devDependencies": { "@vitejs/plugin-react": "^4.2.0", "vite": "catalog:", - "vitest": "^4.0.0", + "vitest": "catalog:", "playwright": "*", "vite-plus": "catalog:" }, @@ -84,11 +84,43 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-monorepo-bun/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-bun/snap.txt index d6d8373235..df11dc19f1 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-bun/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-bun/snap.txt @@ -44,8 +44,15 @@ export default defineConfig({ ], "catalog": { "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "^4.1.5", - "vite-plus": "latest" + "vitest": "4.1.5", + "vite-plus": "latest", + "@vitest/expect": "4.1.5", + "@vitest/runner": "4.1.5", + "@vitest/snapshot": "4.1.5", + "@vitest/spy": "4.1.5", + "@vitest/utils": "4.1.5", + "@vitest/mocker": "4.1.5", + "@vitest/pretty-format": "4.1.5" } }, "scripts": { @@ -67,7 +74,15 @@ export default defineConfig({ }, "packageManager": "bun@", "overrides": { - "vite": "catalog:" + "vite": "catalog:", + "vitest": "catalog:", + "@vitest/expect": "catalog:", + "@vitest/runner": "catalog:", + "@vitest/snapshot": "catalog:", + "@vitest/spy": "catalog:", + "@vitest/utils": "catalog:", + "@vitest/mocker": "catalog:", + "@vitest/pretty-format": "catalog:" } } diff --git a/packages/cli/snap-tests-global/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt index 26c1b943f7..56aff278e7 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt @@ -38,18 +38,50 @@ packages: catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: '@vitejs/plugin-react>vite': 'npm:vite@' 'supertest>superagent': vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' react-click-away-listener>react: peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat packages/app/package.json # check app package.json { diff --git a/packages/cli/snap-tests-global/migration-monorepo-pnpm/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-pnpm/snap.txt index 7311e6729f..ac0588056f 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-pnpm/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-pnpm/snap.txt @@ -69,7 +69,6 @@ export default defineConfig({ "vite-plus": "catalog:" }, "resolutions": { - "vitest": "catalog:", "vue": "3.5.25" }, "packageManager": "pnpm@" @@ -83,17 +82,48 @@ catalog: testnpm2: ^1.0.0 # test comment here to check if the comment is preserved vite: npm:@voidzero-dev/vite-plus-core@latest - vitest: ^4.0.0 + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest minimumReleaseAge: 1440 overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' minimumReleaseAgeExclude: - vite-plus - '@voidzero-dev/*' diff --git a/packages/cli/snap-tests-global/migration-monorepo-yarn4/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-yarn4/snap.txt index 87fca132a8..f4ac551e9a 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-yarn4/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-yarn4/snap.txt @@ -64,7 +64,15 @@ export default defineConfig({ }, "packageManager": "yarn@", "resolutions": { - "vite": "npm:@voidzero-dev/vite-plus-core@latest" + "vite": "npm:@voidzero-dev/vite-plus-core@latest", + "vitest": "4.1.5", + "@vitest/expect": "4.1.5", + "@vitest/runner": "4.1.5", + "@vitest/snapshot": "4.1.5", + "@vitest/spy": "4.1.5", + "@vitest/utils": "4.1.5", + "@vitest/mocker": "4.1.5", + "@vitest/pretty-format": "4.1.5" } } @@ -72,6 +80,14 @@ export default defineConfig({ nodeLinker: node-modules catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest > cat packages/app/package.json # check app package.json diff --git a/packages/cli/snap-tests-global/migration-no-git-repo/snap.txt b/packages/cli/snap-tests-global/migration-no-git-repo/snap.txt index 4cd2b51d70..c4f5c6fe68 100644 --- a/packages/cli/snap-tests-global/migration-no-git-repo/snap.txt +++ b/packages/cli/snap-tests-global/migration-no-git-repo/snap.txt @@ -19,14 +19,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > test -d .vite-hooks && echo 'hooks dir exists' || echo 'no hooks dir' hooks dir exists diff --git a/packages/cli/snap-tests-global/migration-no-hooks-with-husky/snap.txt b/packages/cli/snap-tests-global/migration-no-hooks-with-husky/snap.txt index 5339190285..391bc745f3 100644 --- a/packages/cli/snap-tests-global/migration-no-hooks-with-husky/snap.txt +++ b/packages/cli/snap-tests-global/migration-no-hooks-with-husky/snap.txt @@ -26,14 +26,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > test -d .husky && echo '.husky directory exists' || echo 'No .husky directory' # verify no .husky directory No .husky directory diff --git a/packages/cli/snap-tests-global/migration-no-hooks/snap.txt b/packages/cli/snap-tests-global/migration-no-hooks/snap.txt index 90d7d48ba2..6be606bdce 100644 --- a/packages/cli/snap-tests-global/migration-no-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-no-hooks/snap.txt @@ -17,14 +17,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > test -d .vite-hooks && echo '.vite-hooks directory exists' || echo 'No .vite-hooks directory' # verify no .vite-hooks directory No .vite-hooks directory diff --git a/packages/cli/snap-tests-global/migration-other-hook-tool/snap.txt b/packages/cli/snap-tests-global/migration-other-hook-tool/snap.txt index 7c8162ae5b..6ac820c0b5 100644 --- a/packages/cli/snap-tests-global/migration-other-hook-tool/snap.txt +++ b/packages/cli/snap-tests-global/migration-other-hook-tool/snap.txt @@ -29,11 +29,43 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-oxlintrc-json-with-comments/snap.txt b/packages/cli/snap-tests-global/migration-oxlintrc-json-with-comments/snap.txt index 1c6816b637..1cd39deb25 100644 --- a/packages/cli/snap-tests-global/migration-oxlintrc-json-with-comments/snap.txt +++ b/packages/cli/snap-tests-global/migration-oxlintrc-json-with-comments/snap.txt @@ -49,11 +49,43 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-oxlintrc-jsonc/snap.txt b/packages/cli/snap-tests-global/migration-oxlintrc-jsonc/snap.txt index 355b2ecb59..b33efba071 100644 --- a/packages/cli/snap-tests-global/migration-oxlintrc-jsonc/snap.txt +++ b/packages/cli/snap-tests-global/migration-oxlintrc-jsonc/snap.txt @@ -51,11 +51,43 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-partially-migrated-pre-commit/snap.txt b/packages/cli/snap-tests-global/migration-partially-migrated-pre-commit/snap.txt index 6c63f873c8..f27bb9bbd1 100644 --- a/packages/cli/snap-tests-global/migration-partially-migrated-pre-commit/snap.txt +++ b/packages/cli/snap-tests-global/migration-partially-migrated-pre-commit/snap.txt @@ -24,14 +24,46 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat .husky/pre-commit # hook file should be unchanged (still has bootstrap) . "$(dirname -- "$0")/_/husky.sh" diff --git a/packages/cli/snap-tests-global/migration-prettier-eslint-combo/snap.txt b/packages/cli/snap-tests-global/migration-prettier-eslint-combo/snap.txt index a7e02fda63..42f4a0a93c 100644 --- a/packages/cli/snap-tests-global/migration-prettier-eslint-combo/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier-eslint-combo/snap.txt @@ -28,14 +28,46 @@ Prettier configuration detected. Auto-migrating to Oxfmt... > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > test ! -f eslint.config.mjs # check eslint config is removed > test ! -f .prettierrc.json # check prettier config is removed diff --git a/packages/cli/snap-tests-global/migration-prettier-ignore-unknown/snap.txt b/packages/cli/snap-tests-global/migration-prettier-ignore-unknown/snap.txt index f22e548c62..1a0a4b83ed 100644 --- a/packages/cli/snap-tests-global/migration-prettier-ignore-unknown/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier-ignore-unknown/snap.txt @@ -26,13 +26,45 @@ Prettier configuration detected. Auto-migrating to Oxfmt... > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > test ! -f .prettierrc.json # check prettier config is removed \ No newline at end of file diff --git a/packages/cli/snap-tests-global/migration-prettier-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-prettier-lint-staged/snap.txt index c810f4790f..bd989fead2 100644 --- a/packages/cli/snap-tests-global/migration-prettier-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier-lint-staged/snap.txt @@ -23,14 +23,46 @@ Prettier configuration detected. Auto-migrating to Oxfmt... > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat vite.config.ts # check oxfmt config and staged config merged into vite.config.ts import { defineConfig } from "vite-plus"; diff --git a/packages/cli/snap-tests-global/migration-prettier-pkg-json/snap.txt b/packages/cli/snap-tests-global/migration-prettier-pkg-json/snap.txt index 23ccc2c07f..205af07ef1 100644 --- a/packages/cli/snap-tests-global/migration-prettier-pkg-json/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier-pkg-json/snap.txt @@ -24,14 +24,46 @@ Prettier configuration detected. Auto-migrating to Oxfmt... > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > cat vite.config.ts # check oxfmt config merged into vite.config.ts with semi/singleQuote settings import { defineConfig } from "vite-plus"; diff --git a/packages/cli/snap-tests-global/migration-prettier/snap.txt b/packages/cli/snap-tests-global/migration-prettier/snap.txt index 7614ea5882..f5f3ebe03e 100644 --- a/packages/cli/snap-tests-global/migration-prettier/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier/snap.txt @@ -26,14 +26,46 @@ Prettier configuration detected. Auto-migrating to Oxfmt... > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' > test ! -f .prettierrc.json # check prettier config is removed > cat vite.config.ts # check oxfmt config merged into vite.config.ts diff --git a/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt b/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt index 292f907310..f820188eb3 100644 --- a/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt +++ b/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt @@ -49,11 +49,43 @@ declare module 'vitest/config' { > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt b/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt index 826aa133dc..c947f9a67e 100644 --- a/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt +++ b/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt @@ -44,11 +44,43 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt b/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt index 7b1e4c06c5..69d8ff381c 100644 --- a/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt +++ b/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt @@ -44,11 +44,43 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-standalone-npm/snap.txt b/packages/cli/snap-tests-global/migration-standalone-npm/snap.txt index 8359eb19b6..49dc9a84b7 100644 --- a/packages/cli/snap-tests-global/migration-standalone-npm/snap.txt +++ b/packages/cli/snap-tests-global/migration-standalone-npm/snap.txt @@ -9,12 +9,20 @@ "name": "migration-standalone-npm", "devDependencies": { "vite": "npm:@voidzero-dev/vite-plus-core@latest", - "vitest": "^4.0.0", + "vitest": "4.1.5", "vite-plus": "latest" }, "packageManager": "npm@", "overrides": { - "vite": "npm:@voidzero-dev/vite-plus-core@latest" + "vite": "npm:@voidzero-dev/vite-plus-core@latest", + "vitest": "4.1.5", + "@vitest/expect": "4.1.5", + "@vitest/runner": "4.1.5", + "@vitest/snapshot": "4.1.5", + "@vitest/spy": "4.1.5", + "@vitest/utils": "4.1.5", + "@vitest/mocker": "4.1.5", + "@vitest/pretty-format": "4.1.5" } } diff --git a/packages/cli/snap-tests-global/migration-standalone-pnpm/snap.txt b/packages/cli/snap-tests-global/migration-standalone-pnpm/snap.txt index c76960adbe..2342efa842 100644 --- a/packages/cli/snap-tests-global/migration-standalone-pnpm/snap.txt +++ b/packages/cli/snap-tests-global/migration-standalone-pnpm/snap.txt @@ -9,7 +9,7 @@ "name": "migration-standalone-pnpm", "devDependencies": { "vite": "catalog:", - "vitest": "^4.0.0", + "vitest": "catalog:", "vite-plus": "catalog:" }, "packageManager": "pnpm@" @@ -18,11 +18,43 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides, peerDependencyRules, and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-subpath/snap.txt b/packages/cli/snap-tests-global/migration-subpath/snap.txt index 18f766b639..9dca55906b 100644 --- a/packages/cli/snap-tests-global/migration-subpath/snap.txt +++ b/packages/cli/snap-tests-global/migration-subpath/snap.txt @@ -38,11 +38,43 @@ core.hooksPath is not set > cat foo/pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-tsconfig-esmoduleinterop/snap.txt b/packages/cli/snap-tests-global/migration-tsconfig-esmoduleinterop/snap.txt index 9bfb9613fd..18426b11e0 100644 --- a/packages/cli/snap-tests-global/migration-tsconfig-esmoduleinterop/snap.txt +++ b/packages/cli/snap-tests-global/migration-tsconfig-esmoduleinterop/snap.txt @@ -41,11 +41,43 @@ export default defineConfig({ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-vite-version/snap.txt b/packages/cli/snap-tests-global/migration-vite-version/snap.txt index d7bf4df040..8f6cc8e202 100644 --- a/packages/cli/snap-tests-global/migration-vite-version/snap.txt +++ b/packages/cli/snap-tests-global/migration-vite-version/snap.txt @@ -21,11 +21,43 @@ > cat pnpm-workspace.yaml # check pnpm-workspace.yaml has overrides and catalog catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/migration-vitest-peer-dep/snap.txt b/packages/cli/snap-tests-global/migration-vitest-peer-dep/snap.txt index 6d308e879b..41ec83aefd 100644 --- a/packages/cli/snap-tests-global/migration-vitest-peer-dep/snap.txt +++ b/packages/cli/snap-tests-global/migration-vitest-peer-dep/snap.txt @@ -24,11 +24,43 @@ > cat pnpm-workspace.yaml catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + '@vitest/expect': + '@vitest/runner': + '@vitest/snapshot': + '@vitest/spy': + '@vitest/utils': + '@vitest/mocker': + '@vitest/pretty-format': vite-plus: latest overrides: vite: 'catalog:' + vitest: 'catalog:' + '@vitest/expect': 'catalog:' + '@vitest/runner': 'catalog:' + '@vitest/snapshot': 'catalog:' + '@vitest/spy': 'catalog:' + '@vitest/utils': 'catalog:' + '@vitest/mocker': 'catalog:' + '@vitest/pretty-format': 'catalog:' peerDependencyRules: allowAny: - vite + - vitest + - '@vitest/expect' + - '@vitest/runner' + - '@vitest/snapshot' + - '@vitest/spy' + - '@vitest/utils' + - '@vitest/mocker' + - '@vitest/pretty-format' allowedVersions: vite: '*' + vitest: '*' + '@vitest/expect': '*' + '@vitest/runner': '*' + '@vitest/snapshot': '*' + '@vitest/spy': '*' + '@vitest/utils': '*' + '@vitest/mocker': '*' + '@vitest/pretty-format': '*' diff --git a/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt b/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt index 10a16780d5..73ea17a799 100644 --- a/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt +++ b/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt @@ -30,7 +30,15 @@ vite.config.ts "vite-plus": "catalog:" }, "overrides": { - "vite": "catalog:" + "@vitest/expect": "catalog:", + "@vitest/mocker": "catalog:", + "@vitest/pretty-format": "catalog:", + "@vitest/runner": "catalog:", + "@vitest/snapshot": "catalog:", + "@vitest/spy": "catalog:", + "@vitest/utils": "catalog:", + "vite": "catalog:", + "vitest": "catalog:" }, "engines": { "node": ">=22.12.0" @@ -38,6 +46,14 @@ vite.config.ts "packageManager": "bun@", "catalog": { "vite": "npm:@voidzero-dev/vite-plus-core@latest", + "vitest": "4.1.5", + "@vitest/expect": "4.1.5", + "@vitest/runner": "4.1.5", + "@vitest/snapshot": "4.1.5", + "@vitest/spy": "4.1.5", + "@vitest/utils": "4.1.5", + "@vitest/mocker": "4.1.5", + "@vitest/pretty-format": "4.1.5", "vite-plus": "latest" } } diff --git a/packages/cli/snap-tests-global/new-vite-monorepo/snap.txt b/packages/cli/snap-tests-global/new-vite-monorepo/snap.txt index 46b4e644ce..e3111bcf9c 100644 --- a/packages/cli/snap-tests-global/new-vite-monorepo/snap.txt +++ b/packages/cli/snap-tests-global/new-vite-monorepo/snap.txt @@ -59,14 +59,46 @@ catalog: "@types/node": ^24 typescript: ^5 vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + "@vitest/expect": + "@vitest/runner": + "@vitest/snapshot": + "@vitest/spy": + "@vitest/utils": + "@vitest/mocker": + "@vitest/pretty-format": vite-plus: latest overrides: vite: "catalog:" + vitest: "catalog:" + "@vitest/expect": "catalog:" + "@vitest/runner": "catalog:" + "@vitest/snapshot": "catalog:" + "@vitest/spy": "catalog:" + "@vitest/utils": "catalog:" + "@vitest/mocker": "catalog:" + "@vitest/pretty-format": "catalog:" peerDependencyRules: allowAny: - vite + - vitest + - "@vitest/expect" + - "@vitest/runner" + - "@vitest/snapshot" + - "@vitest/spy" + - "@vitest/utils" + - "@vitest/mocker" + - "@vitest/pretty-format" allowedVersions: vite: "*" + vitest: "*" + "@vitest/expect": "*" + "@vitest/runner": "*" + "@vitest/snapshot": "*" + "@vitest/spy": "*" + "@vitest/utils": "*" + "@vitest/mocker": "*" + "@vitest/pretty-format": "*" > test -f vite-plus-monorepo/.gitignore && echo '.gitignore exists' || echo 'ERROR: .gitignore missing' # verify gitignore renamed from _gitignore .gitignore exists diff --git a/packages/cli/snap-tests/create-org-bundled-monorepo/snap.txt b/packages/cli/snap-tests/create-org-bundled-monorepo/snap.txt index cc31c0c256..d7dffa4da5 100644 --- a/packages/cli/snap-tests/create-org-bundled-monorepo/snap.txt +++ b/packages/cli/snap-tests/create-org-bundled-monorepo/snap.txt @@ -26,14 +26,46 @@ packages: - packages/* catalog: vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: + "@vitest/expect": + "@vitest/runner": + "@vitest/snapshot": + "@vitest/spy": + "@vitest/utils": + "@vitest/mocker": + "@vitest/pretty-format": vite-plus: latest overrides: vite: "catalog:" + vitest: "catalog:" + "@vitest/expect": "catalog:" + "@vitest/runner": "catalog:" + "@vitest/snapshot": "catalog:" + "@vitest/spy": "catalog:" + "@vitest/utils": "catalog:" + "@vitest/mocker": "catalog:" + "@vitest/pretty-format": "catalog:" peerDependencyRules: allowAny: - vite + - vitest + - "@vitest/expect" + - "@vitest/runner" + - "@vitest/snapshot" + - "@vitest/spy" + - "@vitest/utils" + - "@vitest/mocker" + - "@vitest/pretty-format" allowedVersions: vite: "*" + vitest: "*" + "@vitest/expect": "*" + "@vitest/runner": "*" + "@vitest/snapshot": "*" + "@vitest/spy": "*" + "@vitest/utils": "*" + "@vitest/mocker": "*" + "@vitest/pretty-format": "*" > test -d my-mono/.git && echo 'Git initialized' # git-init prompt covers bundled monorepo path Git initialized diff --git a/packages/cli/src/migration/__tests__/migrator.spec.ts b/packages/cli/src/migration/__tests__/migrator.spec.ts index 3125f31154..b88a79ed05 100644 --- a/packages/cli/src/migration/__tests__/migrator.spec.ts +++ b/packages/cli/src/migration/__tests__/migrator.spec.ts @@ -170,9 +170,9 @@ describe('rewritePackageJson', () => { rewritePackageJson(pkg, PackageManager.yarn, true); expect(pkg.devDependencies.vite).toBe('catalog:'); - // vitest is no longer aliased to @voidzero-dev/vite-plus-test; it's left - // untouched so users can keep upstream vitest pinned independently. - expect(pkg.dependencies.vitest).toBe('^4.0.0'); + // vitest is a managed override key — non-catalog specs are rewritten to + // `catalog:` so the override is resolved through the catalog. + expect(pkg.dependencies.vitest).toBe('catalog:'); expect((pkg.devDependencies as Record)['vite-plus']).toBe('catalog:'); }); @@ -191,8 +191,10 @@ describe('rewritePackageJson', () => { expect(pkg.devDependencies.vite).toBe('catalog:'); expect(pkg.optionalDependencies.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); - // vitest is no longer aliased — the catalog: spec is preserved as-is. - expect(pkg.optionalDependencies.vitest).toBe('catalog:test'); + // vitest is now a managed override key — yarn optional deps receive the + // literal override version so the resolution doesn't depend on catalog + // lookup at the optionalDependency site. + expect(pkg.optionalDependencies.vitest).toBe('4.1.5'); expect((pkg.devDependencies as Record)['vite-plus']).toBe('catalog:'); }); @@ -656,9 +658,9 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { const overrides = pnpm.overrides as Record; expect(overrides['some-pkg']).toBe('1.0.0'); expect(overrides.vite).toBeDefined(); - // vitest is no longer injected into overrides — upstream vitest is consumed - // transitively via vite-plus. - expect(overrides.vitest).toBeUndefined(); + // vitest is pinned via overrides so downstream projects resolve a single + // vitest copy (the one vp-cli ships). + expect(overrides.vitest).toBe('4.1.5'); // peerDependencyRules should be present expect(pnpm.peerDependencyRules).toBeDefined(); @@ -704,8 +706,9 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { const yaml = readYaml(path.join(tmpDir, 'pnpm-workspace.yaml')); expect(yaml).toContain("vite: 'catalog:'"); - // vitest is no longer added to overrides — only `vite` is the managed key. - expect(yaml).not.toContain('vitest:'); + // vitest is now a managed override key — it resolves through the catalog + // like vite does. + expect(yaml).toContain("vitest: 'catalog:'"); }); it('rewrites named catalogs in pnpm-workspace.yaml without adding new entries', () => { @@ -748,14 +751,16 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { catalogs: Record>; }; expect(yaml.overrides.vite).toBe('catalog:vite7'); - // vitest is no longer a managed override / aliased catalog entry — pre-existing - // user-defined catalog entries are preserved verbatim. - expect(yaml.overrides.vitest).toBeUndefined(); - expect(yaml.catalog.vitest).toBe('^4.0.0'); + // vitest is now a managed override key — it is added to overrides as a + // `catalog:` reference, and its catalog entry is rewritten to the pinned + // vitest version vp-cli ships. + expect(yaml.overrides.vitest).toBe('catalog:'); + expect(yaml.catalog.vitest).toBe('4.1.5'); expect(yaml.catalogs.vite7.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); expect(yaml.catalogs.vite7.react).toBe('^18.0.0'); expect(yaml.catalogs.vite7['vite-plus']).toBe('latest'); - expect(yaml.catalogs.test.vitest).toBe('^4.0.0'); + // Named catalog vitest entries are also pinned to the managed override version. + expect(yaml.catalogs.test.vitest).toBe('4.1.5'); expect(yaml.catalogs.test.tsdown).toBeUndefined(); expect(yaml.catalogs.test['vite-plus']).toBeUndefined(); @@ -766,8 +771,11 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { expect(pkg.devDependencies.vite).toBe('catalog:vite7'); expect(pkg.devDependencies['vite-plus']).toBe('catalog:'); expect(pkg.peerDependencies.vite).toBe('^7.0.0'); - // vitest peer dep is left untouched (no override → no resolution from catalog). - expect(pkg.peerDependencies.vitest).toBe('catalog:'); + // vitest peer `catalog:` is resolved against the pre-rewrite catalog + // (which still holds the user's `^4.0.0`); only the catalog file itself + // is later rewritten to the pinned vp-cli version. The peer range stays + // as the user wrote it. + expect(pkg.peerDependencies.vitest).toBe('^4.0.0'); expect(pkg.peerDependencies).not.toHaveProperty('tsdown'); }); @@ -798,8 +806,8 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { catalogs: Record>; }; expect(yaml.overrides.vite).toBe('catalog:vite7'); - // vitest is no longer injected into overrides. - expect(yaml.overrides.vitest).toBeUndefined(); + // vitest is now injected into overrides as a managed override key. + expect(yaml.overrides.vitest).toBe('catalog:'); expect(yaml.overrides.react).toBe('^18.0.0'); expect(yaml.catalogs.vite7.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); @@ -843,8 +851,8 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { overrides: Record; }; expect(yaml.overrides.vite).toBe('catalog:'); - // vitest is no longer added to overrides. - expect(yaml.overrides.vitest).toBeUndefined(); + // vitest is now a managed override key — added to overrides as catalog: ref. + expect(yaml.overrides.vitest).toBe('catalog:'); }); it('does not resolve peer dependency catalog specs to migrated aliases', () => { @@ -876,8 +884,9 @@ describe('rewriteStandaloneProject pnpm workspace yaml', () => { peerDependencies: Record; }; expect(pkg.peerDependencies.vite).toBe('*'); - // vitest peer dep is no longer coerced to '*' — vitest isn't a managed key. - expect(pkg.peerDependencies.vitest).toBe('catalog:'); + // vitest is now a managed override key — peer dep catalog refs that + // resolve to the override target are coerced to '*'. + expect(pkg.peerDependencies.vitest).toBe('*'); }); }); @@ -926,8 +935,9 @@ describe('rewriteMonorepo yarn catalog', () => { expect(yarnrc.nodeLinker).toBe('node-modules'); expect(yarnrc.catalogs.vite7.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); expect(yarnrc.catalogs.vite7.react).toBe('^18.0.0'); - // vitest is no longer aliased — its catalog entry is left as the user wrote it. - expect(yarnrc.catalogs.test.vitest).toBe('^4.0.0'); + // vitest is now a managed override key — existing catalog entries are + // rewritten to the pinned vp-cli vitest version. + expect(yarnrc.catalogs.test.vitest).toBe('4.1.5'); expect(yarnrc.catalogs.test.oxlint).toBeUndefined(); const pkg = readJson(path.join(tmpDir, 'package.json')) as { @@ -936,8 +946,10 @@ describe('rewriteMonorepo yarn catalog', () => { }; expect(pkg.devDependencies.vite).toBe('catalog:vite7'); expect(pkg.peerDependencies.vite).toBe('^7.0.0'); - // vitest peer catalog: ref is preserved as-is (no longer treated as a managed override). - expect(pkg.peerDependencies.vitest).toBe('catalog:test'); + // vitest peer `catalog:test` is resolved against the pre-rewrite catalog + // (which still holds the user's `^4.0.0`). The peer range stays as the + // user wrote it; only the catalog file itself is later rewritten. + expect(pkg.peerDependencies.vitest).toBe('^4.0.0'); }); }); @@ -1030,8 +1042,9 @@ describe('rewriteMonorepo bun catalog', () => { expect(pkg.workspaces.catalog.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); expect(pkg.workspaces.catalog['vite-plus']).toBe('latest'); expect(pkg.catalog.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); - // vitest is no longer aliased — pre-existing catalog entries are kept as-is. - expect(pkg.catalog.vitest).toBe('^3.0.0'); + // vitest is now a managed override key — pre-existing catalog entries are + // rewritten to the pinned vp-cli vitest version. + expect(pkg.catalog.vitest).toBe('4.1.5'); expect(pkg.catalog.tsdown).toBeUndefined(); expect(pkg.catalog.react).toBe('^19.0.0'); expect(pkg.catalog['vite-plus']).toBeUndefined(); @@ -1091,14 +1104,17 @@ describe('rewriteMonorepo bun catalog', () => { expect(pkg.catalogs.build.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); expect(pkg.catalogs.build.react).toBe('^19.0.0'); expect(pkg.catalogs.build.tsdown).toBeUndefined(); - // vitest catalog entries and overrides are not synthesized anymore. - expect(pkg.catalogs.test.vitest).toBe('^4.0.0'); + // vitest is now a managed override key — existing catalog entries are + // rewritten to the pinned version and `overrides.vitest` is injected + // as a `catalog:` ref so bun resolves it through the catalog. + expect(pkg.catalogs.test.vitest).toBe('4.1.5'); expect(pkg.overrides.vite).toBe('catalog:build'); - expect(pkg.overrides.vitest).toBeUndefined(); + expect(pkg.overrides.vitest).toBe('catalog:'); expect(pkg.devDependencies.vite).toBe('catalog:build'); expect(pkg.peerDependencies.vite).toBe('^7.0.0'); - // vitest peer catalog: ref is preserved as-is. - expect(pkg.peerDependencies.vitest).toBe('catalog:test'); + // vitest peer `catalog:test` is resolved against the pre-rewrite catalog + // (which still holds the user's `^4.0.0`). Peer range stays as-is. + expect(pkg.peerDependencies.vitest).toBe('^4.0.0'); }); it('rewrites workspaces named catalogs and writes default catalog beside them', () => { @@ -1133,8 +1149,9 @@ describe('rewriteMonorepo bun catalog', () => { expect(pkg.workspaces.catalog['vite-plus']).toBe('latest'); expect(pkg.workspaces.catalogs.build.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); expect(pkg.workspaces.catalogs.build.oxlint).toBeUndefined(); - // vitest catalog entries are preserved verbatim, not aliased. - expect(pkg.workspaces.catalogs.test.vitest).toBe('^4.0.0'); + // vitest is a managed override key — existing catalog entries are + // rewritten to the pinned vp-cli vitest version. + expect(pkg.workspaces.catalogs.test.vitest).toBe('4.1.5'); expect(pkg.workspaces.catalogs.test.vite).toBe('npm:@voidzero-dev/vite-plus-core@latest'); expect(pkg.overrides.vite).toBe('catalog:'); }); diff --git a/packages/cli/src/migration/migrator.ts b/packages/cli/src/migration/migrator.ts index 06366f236f..8bc288fabb 100644 --- a/packages/cli/src/migration/migrator.ts +++ b/packages/cli/src/migration/migrator.ts @@ -28,6 +28,7 @@ import { VITE_PLUS_NAME, VITE_PLUS_OVERRIDE_PACKAGES, VITE_PLUS_VERSION, + VITEST_VERSION, isForceOverrideMode, } from '../utils/constants.ts'; import { editJsonFile, isJsonFile, readJsonFile } from '../utils/json.ts'; @@ -108,7 +109,7 @@ const LEGACY_WRAPPER_PACKAGE_NAMES = ['@voidzero-dev/vite-plus-test'] as const; // rewritten. For `vitest`, we substitute the vitest version vite-plus // bundles so any `catalog:` reference the user still has resolves cleanly. const LEGACY_WRAPPER_FALLBACK_VERSIONS: Record = { - vitest: '^4.1.5', + vitest: `^${VITEST_VERSION}`, }; function isLegacyWrapperSpec(value: string | undefined): boolean { @@ -1995,7 +1996,11 @@ export function rewritePackageJson( !installableDeps.vitest && Object.keys(installableDeps).some((name) => name.includes('vitest')) ) { - pkg.devDependencies.vitest = getCatalogDependencySpec(undefined, '4.1.5', supportCatalog); + pkg.devDependencies.vitest = getCatalogDependencySpec( + undefined, + VITEST_VERSION, + supportCatalog, + ); } } return extractedStagedConfig; diff --git a/packages/cli/src/utils/constants.ts b/packages/cli/src/utils/constants.ts index 9613514273..c452672592 100644 --- a/packages/cli/src/utils/constants.ts +++ b/packages/cli/src/utils/constants.ts @@ -3,10 +3,20 @@ import { createRequire } from 'node:module'; export const VITE_PLUS_NAME = 'vite-plus'; export const VITE_PLUS_VERSION = process.env.VP_VERSION || 'latest'; +export const VITEST_VERSION = '4.1.5'; + export const VITE_PLUS_OVERRIDE_PACKAGES: Record = process.env.VP_OVERRIDE_PACKAGES ? JSON.parse(process.env.VP_OVERRIDE_PACKAGES) : { vite: 'npm:@voidzero-dev/vite-plus-core@latest', + vitest: VITEST_VERSION, + '@vitest/expect': VITEST_VERSION, + '@vitest/runner': VITEST_VERSION, + '@vitest/snapshot': VITEST_VERSION, + '@vitest/spy': VITEST_VERSION, + '@vitest/utils': VITEST_VERSION, + '@vitest/mocker': VITEST_VERSION, + '@vitest/pretty-format': VITEST_VERSION, }; /** From cbf6bc1ae7321f7a914db26d49a9d8014dcb1815 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 13:43:42 +0800 Subject: [PATCH 17/37] fix(cli): accept `test` field in defineConfig type signature User configs like `defineConfig({ test: { globals: true } })` were failing tsc with TS2769 because vite-plus's defineConfig typed its parameter as vite-plus-core's UserConfig, which doesn't get vitest's `declare module 'vite'` augmentation (vite-plus-core is a fork). Extend the local `declare module '@voidzero-dev/vite-plus-core'` augmentation to add `test?: VitestInlineConfig`. New unit test locks the behavior in. --- .../define-config-test-field.spec.ts | 27 +++++++++++++++++++ packages/cli/src/define-config.ts | 11 ++++++++ 2 files changed, 38 insertions(+) create mode 100644 packages/cli/src/__tests__/define-config-test-field.spec.ts diff --git a/packages/cli/src/__tests__/define-config-test-field.spec.ts b/packages/cli/src/__tests__/define-config-test-field.spec.ts new file mode 100644 index 0000000000..f4978713f8 --- /dev/null +++ b/packages/cli/src/__tests__/define-config-test-field.spec.ts @@ -0,0 +1,27 @@ +import { describe, it } from 'vitest'; + +import { defineConfig } from '../index.js'; + +describe('defineConfig test field typing', () => { + it('accepts test config without TS error', () => { + const cfg = defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.spec.ts'], + }, + }); + void cfg; + }); + + it('accepts test config alongside other vite-plus fields', () => { + const cfg = defineConfig({ + test: { + globals: true, + environment: 'jsdom', + }, + lint: {}, + }); + void cfg; + }); +}); diff --git a/packages/cli/src/define-config.ts b/packages/cli/src/define-config.ts index e7689511cd..d0d442735d 100644 --- a/packages/cli/src/define-config.ts +++ b/packages/cli/src/define-config.ts @@ -2,6 +2,7 @@ import type { PluginOption, UserConfig } from '@voidzero-dev/vite-plus-core'; import type { OxfmtConfig } from 'oxfmt'; import type { OxlintConfig } from 'oxlint'; import { defineConfig as viteDefineConfig, type ConfigEnv } from 'vitest/config'; +import type { InlineConfig as VitestInlineConfig } from 'vitest/node'; import type { PackUserConfig } from './pack.ts'; import type { RunConfig } from './run-config.ts'; @@ -36,6 +37,16 @@ declare module '@voidzero-dev/vite-plus-core' { */ defaultTemplate?: string; }; + + /** + * Vitest test configuration. + * + * Vitest augments vite's `UserConfig` with a `test` field via + * `declare module 'vite'`, but vite-plus-core is a fork of vite so that + * augmentation does not apply here. Re-declare it locally so user + * configs like `defineConfig({ test: { globals: true } })` typecheck. + */ + test?: VitestInlineConfig; } } From ba585b76ece022275597f8fa0a5479175fbd6971 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 13:48:47 +0800 Subject: [PATCH 18/37] fix(cli): inject vitest specifier rewrite plugin into defineConfig @vitest/mocker's static hoister only recognizes 'vitest' as the mock-API source string. User configs from migrated projects import `vi` from 'vite-plus/test', which mocker doesn't see, so vi.mock() fails at runtime with "problems in resolving the mocks API". Inject a pre-stage Vite plugin into vite-plus's defineConfig wrapper that rewrites bare `from 'vite-plus/test'` -> `from 'vitest'` in user source. Subpaths are left alone. Override pinning (task #50) guarantees both specifiers resolve to the same module so this is runtime-safe. This is a workaround until @vitest/mocker accepts a configurable hoistedModule option upstream. --- .../define-config-mocker-rewrite.spec.ts | 68 +++++++++++++++++++ packages/cli/src/__tests__/index.spec.ts | 44 ++++++++---- packages/cli/src/define-config.ts | 63 ++++++++++++++++- 3 files changed, 159 insertions(+), 16 deletions(-) create mode 100644 packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts diff --git a/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts b/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts new file mode 100644 index 0000000000..be0757c239 --- /dev/null +++ b/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts @@ -0,0 +1,68 @@ +import { describe, expect, it } from 'vitest'; + +import { rewriteVitePlusTestSpecifier } from '../define-config.ts'; + +describe('rewriteVitePlusTestSpecifier', () => { + it('is a no-op when source does not mention vite-plus/test', () => { + const code = "import { describe } from 'vitest';\nimport * as fs from 'node:fs';\n"; + expect(rewriteVitePlusTestSpecifier(code)).toBe(code); + }); + + it("rewrites `from 'vite-plus/test'` to `from 'vitest'`", () => { + const input = "import { vi } from 'vite-plus/test';\nvi.mock('./foo');\n"; + const expected = "import { vi } from 'vitest';\nvi.mock('./foo');\n"; + expect(rewriteVitePlusTestSpecifier(input)).toBe(expected); + }); + + it('rewrites the double-quoted form too', () => { + const input = 'import { vi } from "vite-plus/test";\n'; + const expected = 'import { vi } from "vitest";\n'; + expect(rewriteVitePlusTestSpecifier(input)).toBe(expected); + }); + + it('does NOT rewrite subpaths such as vite-plus/test/browser', () => { + const input = "import { context } from 'vite-plus/test/browser';\n"; + expect(rewriteVitePlusTestSpecifier(input)).toBe(input); + }); + + it('does NOT rewrite a bare string literal containing vite-plus/test', () => { + const input = "const x = 'vite-plus/test';\nconsole.log(x);\n"; + expect(rewriteVitePlusTestSpecifier(input)).toBe(input); + }); + + it("rewrites dynamic `import('vite-plus/test')`", () => { + const input = "const mod = await import('vite-plus/test');\n"; + const expected = "const mod = await import('vitest');\n"; + expect(rewriteVitePlusTestSpecifier(input)).toBe(expected); + }); + + it("rewrites `require('vite-plus/test')` while leaving the subpath form alone", () => { + const input = [ + "const a = require('vite-plus/test');", + "const b = require('vite-plus/test/browser');", + '', + ].join('\n'); + const expected = [ + "const a = require('vitest');", + "const b = require('vite-plus/test/browser');", + '', + ].join('\n'); + expect(rewriteVitePlusTestSpecifier(input)).toBe(expected); + }); + + it('preserves all other imports in the file', () => { + const input = [ + "import { describe, it, expect } from 'vite-plus/test';", + "import * as fs from 'node:fs';", + "import { something } from 'vite-plus/test/browser';", + '', + ].join('\n'); + const expected = [ + "import { describe, it, expect } from 'vitest';", + "import * as fs from 'node:fs';", + "import { something } from 'vite-plus/test/browser';", + '', + ].join('\n'); + expect(rewriteVitePlusTestSpecifier(input)).toBe(expected); + }); +}); diff --git a/packages/cli/src/__tests__/index.spec.ts b/packages/cli/src/__tests__/index.spec.ts index 25de62f9a3..161e082bd6 100644 --- a/packages/cli/src/__tests__/index.spec.ts +++ b/packages/cli/src/__tests__/index.spec.ts @@ -90,6 +90,17 @@ test('lazyPlugins wraps sync function returning a Promise into array', () => { expect(result).not.toBeInstanceOf(Promise); }); +// defineConfig auto-injects a `vite-plus:vitest-specifier-rewrite` plugin at +// index 0 so user-supplied plugins start at index 1. The helpers below let the +// tests assert on user-supplied plugins regardless of the injection. +const REWRITE_PLUGIN_NAME = 'vite-plus:vitest-specifier-rewrite'; +const userPlugins = (plugins: unknown): unknown[] => { + expect(Array.isArray(plugins)).toBe(true); + const arr = plugins as unknown[]; + expect((arr[0] as { name?: string })?.name).toBe(REWRITE_PLUGIN_NAME); + return arr.slice(1); +}; + // lazyPlugins type compatibility tests — these verify at compile time that // lazyPlugins return types satisfy Vite's plugins?: PluginOption[] field. @@ -99,7 +110,7 @@ test('lazyPlugins sync return type satisfies plugins field', () => { const config = defineConfig({ plugins: lazyPlugins(() => [{ name: 'sync-type-test' }]), }); - expect(config.plugins?.length).toBe(1); + expect(userPlugins(config.plugins).length).toBe(1); }); test('lazyPlugins async return type satisfies plugins field', () => { @@ -119,7 +130,8 @@ test('lazyPlugins undefined return satisfies plugins field', () => { const config = defineConfig({ plugins: lazyPlugins(() => [{ name: 'skipped' }]), }); - expect(config.plugins).toBeUndefined(); + // lazyPlugins returns undefined, but defineConfig still injects its rewrite plugin. + expect(userPlugins(config.plugins).length).toBe(0); }); test('lazyPlugins with vitest configureVitest plugin satisfies plugins field', () => { @@ -132,7 +144,7 @@ test('lazyPlugins with vitest configureVitest plugin satisfies plugins field', ( }, ]), }); - expect(config.plugins?.length).toBe(1); + expect(userPlugins(config.plugins).length).toBe(1); }); // defineConfig compatibility tests @@ -141,35 +153,35 @@ test('defineConfig passes through plain plugins array', () => { const config = defineConfig({ plugins: [{ name: 'test-plugin' }], }); - expect(config.plugins?.length).toBe(1); + expect(userPlugins(config.plugins).length).toBe(1); }); test('defineConfig supports Plugin objects in plugins array', () => { const config = defineConfig({ plugins: [{ name: 'plugin-a' }, { name: 'plugin-b' }], }); - expect(config.plugins?.length).toBe(2); + expect(userPlugins(config.plugins).length).toBe(2); }); test('defineConfig supports falsy values in plugins array', () => { const config = defineConfig({ plugins: [{ name: 'real-plugin' }, false, null, undefined], }); - expect(config.plugins?.length).toBe(4); + expect(userPlugins(config.plugins).length).toBe(4); }); test('defineConfig supports nested plugin arrays', () => { const config = defineConfig({ plugins: [[{ name: 'nested-a' }, { name: 'nested-b' }], { name: 'top-level' }], }); - expect(config.plugins?.length).toBe(2); + expect(userPlugins(config.plugins).length).toBe(2); }); test('defineConfig supports Promise in plugins array', () => { const config = defineConfig({ plugins: [Promise.resolve({ name: 'async-plugin' })], }); - expect(config.plugins?.length).toBe(1); + expect(userPlugins(config.plugins).length).toBe(1); }); test('defineConfig supports mixed PluginOption types in array', () => { @@ -183,19 +195,20 @@ test('defineConfig supports mixed PluginOption types in array', () => { undefined, ], }); - expect(config.plugins?.length).toBe(6); + expect(userPlugins(config.plugins).length).toBe(6); }); test('defineConfig supports empty plugins array', () => { const config = defineConfig({ plugins: [], }); - expect(config.plugins?.length).toBe(0); + expect(userPlugins(config.plugins).length).toBe(0); }); test('defineConfig supports config without plugins', () => { const config = defineConfig({}); - expect(config.plugins).toBeUndefined(); + // defineConfig always injects its rewrite plugin even when user omits `plugins`. + expect(userPlugins(config.plugins).length).toBe(0); }); test('defineConfig supports function config with plain plugins array', () => { @@ -203,7 +216,7 @@ test('defineConfig supports function config with plain plugins array', () => { plugins: [{ name: 'fn-plugin' }], })); const config = configFn({ command: 'build', mode: 'production' }); - expect(config.plugins?.length).toBe(1); + expect(userPlugins(config.plugins).length).toBe(1); }); test('defineConfig supports async function config with plain plugins array', async () => { @@ -211,7 +224,7 @@ test('defineConfig supports async function config with plain plugins array', asy plugins: [{ name: 'async-fn-plugin' }], })); const config = await configFn({ command: 'build', mode: 'production' }); - expect(config.plugins?.length).toBe(1); + expect(userPlugins(config.plugins).length).toBe(1); }); test('defineConfig supports vitest plugin with configureVitest hook', () => { @@ -225,6 +238,7 @@ test('defineConfig supports vitest plugin with configureVitest hook', () => { }, ], }); - expect(config.plugins?.length).toBe(1); - expect((config.plugins?.[0] as { name: string })?.name).toBe('vitest-plugin'); + const userOnly = userPlugins(config.plugins); + expect(userOnly.length).toBe(1); + expect((userOnly[0] as { name: string })?.name).toBe('vitest-plugin'); }); diff --git a/packages/cli/src/define-config.ts b/packages/cli/src/define-config.ts index d0d442735d..6f3322f5b0 100644 --- a/packages/cli/src/define-config.ts +++ b/packages/cli/src/define-config.ts @@ -60,6 +60,67 @@ type ViteUserConfigExport = | ViteUserConfigFnPromise | ViteUserConfigFn; +/** + * Rewrite bare-root `vite-plus/test` import specifiers to `vitest` so that + * `@vitest/mocker`'s static hoister (which hardcodes `hoistedModule = "vitest"`) + * recognizes calls like `vi.mock(...)`. Subpaths such as + * `vite-plus/test/browser` are intentionally left unchanged. + * + * Task #50 pins `vitest` and the `@vitest/*` family so both specifiers resolve + * to the same physical module, making this rewrite runtime-safe. + * + * Exported for unit testing. + */ +export function rewriteVitePlusTestSpecifier(code: string): string { + if (!code.includes('vite-plus/test')) { + return code; + } + return code + .replace(/(from\s+['"])vite-plus\/test(?=['"])/g, '$1vitest') + .replace(/(import\s*\(\s*['"])vite-plus\/test(?=['"])/g, '$1vitest') + .replace(/(require\s*\(\s*['"])vite-plus\/test(?=['"])/g, '$1vitest'); +} + +function vitePlusTestSpecifierRewritePlugin(): PluginOption { + return { + name: 'vite-plus:vitest-specifier-rewrite', + enforce: 'pre', + transform(code, id) { + if (id.includes('/node_modules/')) { + return null; + } + const newCode = rewriteVitePlusTestSpecifier(code); + if (newCode === code) { + return null; + } + return { code: newCode, map: null }; + }, + }; +} + +function injectPlugin(config: UserConfig): UserConfig { + return { + ...config, + plugins: [vitePlusTestSpecifierRewritePlugin(), ...(config.plugins ?? [])], + }; +} + +function injectPluginIntoConfig(config: ViteUserConfigExport): ViteUserConfigExport { + if (typeof config === 'function') { + return (env: ConfigEnv) => { + const result = config(env); + if (result instanceof Promise) { + return result.then(injectPlugin); + } + return injectPlugin(result); + }; + } + if (config instanceof Promise) { + return config.then(injectPlugin); + } + return injectPlugin(config); +} + export function defineConfig(config: UserConfig): UserConfig; export function defineConfig(config: Promise): Promise; export function defineConfig(config: ViteUserConfigFnObject): ViteUserConfigFnObject; @@ -67,7 +128,7 @@ export function defineConfig(config: ViteUserConfigFnPromise): ViteUserConfigFnP export function defineConfig(config: ViteUserConfigExport): ViteUserConfigExport; export function defineConfig(config: ViteUserConfigExport): ViteUserConfigExport { - return viteDefineConfig(config); + return viteDefineConfig(injectPluginIntoConfig(config)); } const VITE_COMMANDS = new Set(['dev', 'build', 'test', 'preview']); From 5b725046c1abb121b981df601d2e8148cc091560 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 14:14:42 +0800 Subject: [PATCH 19/37] fix(cli): resolve mergeConfig star-export conflict between core and vitest/config `export * from '@voidzero-dev/vite-plus-core'` and `export * from 'vitest/config'` both expose `mergeConfig` (and a handful of other vite-from-vitest re-exports). Per the ES spec, two star-exports of the same name make any named import fail with a SyntaxError -- breaking frm-stack and any other config that imports `mergeConfig` from `vite-plus`. Switch the vitest/config re-export to an explicit list of names unique to vitest (configDefaults, coverageConfigDefaults, etc), leaving the shared names (mergeConfig, loadConfigFromFile, ...) to come from vite-plus-core only. --- .../define-config-test-field.spec.ts | 22 +++++++++++++++++-- packages/cli/src/index.ts | 9 +++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/__tests__/define-config-test-field.spec.ts b/packages/cli/src/__tests__/define-config-test-field.spec.ts index f4978713f8..f3a787b65f 100644 --- a/packages/cli/src/__tests__/define-config-test-field.spec.ts +++ b/packages/cli/src/__tests__/define-config-test-field.spec.ts @@ -1,6 +1,12 @@ -import { describe, it } from 'vitest'; +import { describe, expect, it } from 'vitest'; -import { defineConfig } from '../index.js'; +import { + configDefaults, + coverageConfigDefaults, + defineConfig, + loadConfigFromFile, + mergeConfig, +} from '../index.js'; describe('defineConfig test field typing', () => { it('accepts test config without TS error', () => { @@ -24,4 +30,16 @@ describe('defineConfig test field typing', () => { }); void cfg; }); + + it('re-exports shared and vitest-specific names without star-export conflicts', () => { + expect(typeof defineConfig).toBe('function'); + expect(typeof mergeConfig).toBe('function'); + expect(typeof loadConfigFromFile).toBe('function'); + expect(typeof configDefaults).toBe('object'); + expect(typeof coverageConfigDefaults).toBe('object'); + + const merged = mergeConfig({ test: { globals: true } }, { test: { environment: 'node' } }); + expect(merged.test.globals).toBe(true); + expect(merged.test.environment).toBe('node'); + }); }); diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 6c01777f7f..cf796c9d9d 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -2,6 +2,13 @@ import { defineConfig, lazyPlugins } from './define-config.ts'; export * from '@voidzero-dev/vite-plus-core'; -export * from 'vitest/config'; +export { + configDefaults, + coverageConfigDefaults, + defaultBrowserPort, + defaultExclude, + defaultInclude, + defineProject, +} from 'vitest/config'; export { defineConfig, lazyPlugins }; From 427e9295e61bc7b4fbd2d9e87e27995f83bc89ab Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 14:21:58 +0800 Subject: [PATCH 20/37] test(snap): redact transient network warnings in snap output A one-off ECONNRESET on the pnpm registry got baked into command-add-pnpm11-with-workspace/snap.txt, then never reproduced, making the snap permanently diff against live runs. While fixing, discovered the existing pnpm WARN redaction regexes contained U+2009 thin-space characters in their patterns, so they never matched real pnpm output -- only test fixtures that also contained thin spaces. Normalize all 4 WARN regexes to ASCII space, and broaden the GET-registry pattern to drop transient network warnings like `[WARN] GET ... error (ECONNRESET). Will retry ...` so single-run flakes don't get baked into snapshots. --- .../snap.txt | 1 - .../__snapshots__/utils.spec.ts.snap | 7 +++--- packages/tools/src/__tests__/utils.spec.ts | 25 +++++++++++++------ packages/tools/src/utils.ts | 12 ++++++--- 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/packages/cli/snap-tests-global/command-add-pnpm11-with-workspace/snap.txt b/packages/cli/snap-tests-global/command-add-pnpm11-with-workspace/snap.txt index 6bd8bbb3c2..6e882943ac 100644 --- a/packages/cli/snap-tests-global/command-add-pnpm11-with-workspace/snap.txt +++ b/packages/cli/snap-tests-global/command-add-pnpm11-with-workspace/snap.txt @@ -93,7 +93,6 @@ Done in ms using pnpm v } > vp add -E testnpm2 test-vite-plus-install --filter "*" && cat package.json packages/app/package.json packages/utils/package.json # should add testnpm2 test-vite-plus-install to all packages except workspace root -[WARN] GET https://registry./testnpm2 error (ECONNRESET). Will retry in 10 seconds. 2 retries left. Progress: resolved , reused , downloaded , added , done Done in ms using pnpm v { diff --git a/packages/tools/src/__tests__/__snapshots__/utils.spec.ts.snap b/packages/tools/src/__tests__/__snapshots__/utils.spec.ts.snap index e90d2192b4..4bdecf2b09 100644 --- a/packages/tools/src/__tests__/__snapshots__/utils.spec.ts.snap +++ b/packages/tools/src/__tests__/__snapshots__/utils.spec.ts.snap @@ -1,5 +1,7 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[`replaceUnstableOutput() > replace bracketed pnpm registry request error warning log 1`] = `"Progress: resolved"`; + exports[`replaceUnstableOutput() > replace date 1`] = ` "Start at " @@ -47,10 +49,7 @@ exports[`replaceUnstableOutput() > replace ignore pnpm request warning log 1`] = Packages:" `; -exports[`replaceUnstableOutput() > replace ignore tarball download average speed warning log 1`] = ` -"WARN  Tarball download average speed 29 KiB/s (size 56 KiB) is below 50 KiB/s: https://registry./qs/-/qs-6.14.0.tgz (GET) - WARN  Tarball download average speed 34 KiB/s (size 347 KiB) is below 50 KiB/s: https://registry./undici/-/undici-7.16.0.tgz (GET)" -`; +exports[`replaceUnstableOutput() > replace ignore tarball download average speed warning log 1`] = `""`; exports[`replaceUnstableOutput() > replace pnpm progress plus markers with 1`] = ` "Scope: all workspace projects diff --git a/packages/tools/src/__tests__/utils.spec.ts b/packages/tools/src/__tests__/utils.spec.ts index 852d450a39..ebe71ed357 100644 --- a/packages/tools/src/__tests__/utils.spec.ts +++ b/packages/tools/src/__tests__/utils.spec.ts @@ -73,8 +73,8 @@ Packages: +312 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Progress: resolved 1, reused 0, downloaded 0, added 0 Progress: resolved 316, reused 316, downloaded 0, added 315 -WARN  Skip adding vite to the default catalog because it already exists as npm:vite-plus. Please use \`pnpm update\` to update the catalogs. -WARN  Skip adding vitest to the default catalog because it already exists as beta. Please use \`pnpm update\` to update the catalogs. +WARN Skip adding vite to the default catalog because it already exists as npm:vite-plus. Please use \`pnpm update\` to update the catalogs. +WARN Skip adding vitest to the default catalog because it already exists as beta. Please use \`pnpm update\` to update the catalogs. Progress: resolved 316, reused 316, downloaded 0, added 316, done devDependencies: @@ -185,7 +185,7 @@ Done in 171ms using pnpm v10.16.1 test('replace ignore pnpm request warning log', () => { const output = ` Foo bar - WARN  Request took ms: https://registry.npmjs.org/testnpm2 + WARN Request took ms: https://registry.npmjs.org/testnpm2 Packages: `; expect(replaceUnstableOutput(output.trim())).toMatchSnapshot(); @@ -217,20 +217,31 @@ https://registry.yarnpkg.com/testnpm2/-/testnpm2-1.0.0.tgz test('replace pnpm registry request error warning log', () => { const output = ` - WARN  GET https://registry.npmjs.org/test-vite-plus-install error (ECONNRESET). Will retry in 10 seconds. 2 retries left. + WARN GET https://registry.npmjs.org/test-vite-plus-install error (ECONNRESET). Will retry in 10 seconds. 2 retries left. Progress: resolved `; expect(replaceUnstableOutput(output.trim())).toMatchSnapshot(); }); - test('replace ignore tarball download average speed warning log', () => { + test('replace bracketed pnpm registry request error warning log', () => { + // pnpm v11 prints transient network errors with a bracketed `[WARN]` prefix + // and an ASCII space. Make sure the redactor drops these so single-run + // ECONNRESET/ENOTFOUND flakes don't get baked into snap.txt. const output = ` - WARN  Tarball download average speed 29 KiB/s (size 56 KiB) is below 50 KiB/s: https://registry.npmjs.org/qs/-/qs-6.14.0.tgz (GET) - WARN  Tarball download average speed 34 KiB/s (size 347 KiB) is below 50 KiB/s: https://registry.npmjs.org/undici/-/undici-7.16.0.tgz (GET) +[WARN] GET https://registry.npmjs.org/testnpm2 error (ECONNRESET). Will retry in 10 seconds. 2 retries left. +[WARN] GET https://registry.npmjs.org/testnpm2 error (ETIMEDOUT). Will retry in 10 seconds. 1 retries left. +Progress: resolved `; expect(replaceUnstableOutput(output.trim())).toMatchSnapshot(); }); + test('replace ignore tarball download average speed warning log', () => { + const output = ` WARN Tarball download average speed 29 KiB/s (size 56 KiB) is below 50 KiB/s: https://registry.npmjs.org/qs/-/qs-6.14.0.tgz (GET) + WARN Tarball download average speed 34 KiB/s (size 347 KiB) is below 50 KiB/s: https://registry.npmjs.org/undici/-/undici-7.16.0.tgz (GET) +`; + expect(replaceUnstableOutput(output)).toMatchSnapshot(); + }); + test('replace hash values', () => { const output = ` npm notice shasum: 65c35f9599054722ecde040abd4a19682a723cdc diff --git a/packages/tools/src/utils.ts b/packages/tools/src/utils.ts index b9762d8ffe..7825bca333 100644 --- a/packages/tools/src/utils.ts +++ b/packages/tools/src/utils.ts @@ -80,12 +80,16 @@ export function replaceUnstableOutput(output: string, cwd?: string) { // ignore pnpm progress .replaceAll(/Progress: resolved \d+, reused \d+, downloaded \d+, added \d+\n/g, '') // ignore pnpm warn - .replaceAll(/ ?WARN\s+Skip\s+adding .+?\n/g, '') - .replaceAll(/ ?WARN\s+Request\s+took .+?\n/g, '') + .replaceAll(/ ?WARN\s+Skip\s+adding .+?\n/g, '') + .replaceAll(/ ?WARN\s+Request\s+took .+?\n/g, '') .replaceAll(/Scope: all \d+ workspace projects/g, 'Scope: all workspace projects') .replaceAll(/\+{2,}\n/g, '+\n') // ignore pnpm registry request error warning log - .replaceAll(/ ?WARN\s+GET\s+https:\/\/registry\..+?\n/g, '') + // Matches both `WARN` (older pnpm) and `[WARN]` (newer pnpm) prefixes. + // Also drops transient network warnings like + // `[WARN] GET https://registry./pkg error (ECONNRESET). Will retry in 10 seconds. 2 retries left.` + // so single-run flakes don't get baked into snapshots. + .replaceAll(/ ?\[?WARN\]?\s+GET\s+https:\/\/registry\..+?\n/g, '') // ignore bun resolution progress (appears intermittently depending on cache state) .replaceAll(/Resolving dependencies\n/g, '') .replaceAll(/Resolved, downloaded and extracted \[\d+\]\n/g, '') @@ -138,7 +142,7 @@ export function replaceUnstableOutput(output: string, cwd?: string) { // ignore npm registry domain .replaceAll(/(https?:\/\/registry\.)[^/\s]+(\/?)/g, '$1$2') // ignore pnpm tarball download average speed warning log - .replaceAll(/ WARN  Tarball download average speed .+?\n/g, '') + .replaceAll(/ ?\[?WARN\]?\s+Tarball download average speed .+?\n/g, '') // ignore npm hash values .replaceAll(/shasum: .+?\n/g, 'shasum: \n') .replaceAll(/integrity: ([\w-]+)-.+?\n/g, 'integrity: $1-\n') From c58717deb5ac02a0b370eca30ee96448eec33c18 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 14:28:24 +0800 Subject: [PATCH 21/37] fix(migration): override @vitest/coverage-* family npmx.dev pins @vitest/coverage-v8@4.1.0 alongside vitest. Without overriding coverage-v8 to match VITEST_VERSION (4.1.5), pnpm installs two physical copies of @vitest/mocker on disk and vitest's runtime mocks-API check (`vi` came from the same mocker copy as the hoister registered) fails. Co-Authored-By: Claude Opus 4.7 --- ecosystem-ci/patch-project.ts | 2 ++ packages/cli/src/utils/constants.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ecosystem-ci/patch-project.ts b/ecosystem-ci/patch-project.ts index 8c85e033dd..0a178c4dec 100644 --- a/ecosystem-ci/patch-project.ts +++ b/ecosystem-ci/patch-project.ts @@ -68,6 +68,8 @@ const vitestOverrides = { '@vitest/utils': VITEST_VERSION, '@vitest/mocker': VITEST_VERSION, '@vitest/pretty-format': VITEST_VERSION, + '@vitest/coverage-v8': VITEST_VERSION, + '@vitest/coverage-istanbul': VITEST_VERSION, }; execSync(`${cli} migrate --no-agent --no-interactive`, { diff --git a/packages/cli/src/utils/constants.ts b/packages/cli/src/utils/constants.ts index c452672592..71e3ae77d3 100644 --- a/packages/cli/src/utils/constants.ts +++ b/packages/cli/src/utils/constants.ts @@ -17,6 +17,8 @@ export const VITE_PLUS_OVERRIDE_PACKAGES: Record = process.env.V '@vitest/utils': VITEST_VERSION, '@vitest/mocker': VITEST_VERSION, '@vitest/pretty-format': VITEST_VERSION, + '@vitest/coverage-v8': VITEST_VERSION, + '@vitest/coverage-istanbul': VITEST_VERSION, }; /** From d0df69ecc9d750e1bbdf6cc86a468f7a863b2ca5 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 14:45:04 +0800 Subject: [PATCH 22/37] fix(migration): rewrite `from 'vite-plus/test'` -> `from 'vitest'` @vitest/mocker's static hoister hardcodes `hoistedModule = 'vitest'` and runs as part of vitest's own plugin pipeline that executes before user plugins -- so the previously-shipped runtime plugin (d69fe037c) cannot intercept it for `vi.mock` calls. Move the rewrite into the Rust migrator so source is fixed at migrate-time and the mocker sees the canonical specifier. The runtime plugin stays as a safety net for code authored after migration. Concretely: - Drop the forward `'vitest'` -> `'vite-plus/test'` ast-grep rule (the bare-root specifier is now intentionally preserved). - Add a reverse `'vite-plus/test'` -> `'vitest'` ast-grep rule that is anchored to the exact root specifier; subpaths such as `'vite-plus/test/browser-playwright'` are intentionally left untouched because they map to dedicated vite-plus shim exports. - Mirror the same change for `/// ` triple-slash directives. - Update existing tests to expect the new behaviour and add dedicated forward + negative coverage for the reverse rewrite. Co-Authored-By: Claude Opus 4.7 --- crates/vite_migration/src/import_rewriter.rs | 260 +++++++++++++----- .../snap.txt | 2 +- .../command-outdated-pnpm10/snap.txt | 2 +- .../migration-add-git-hooks/snap.txt | 8 + .../snap.txt | 8 + .../migration-baseurl-tsconfig/snap.txt | 8 + .../snap.txt | 8 + .../snap.txt | 8 + .../migration-composed-husky-prepare/snap.txt | 8 + .../migration-env-prefix-lint-staged/snap.txt | 8 + .../migration-eslint-lint-staged/snap.txt | 8 + .../migration-eslint-lintstagedrc/snap.txt | 8 + .../migration-eslint-npx-wrapper/snap.txt | 8 + .../migration-eslint/snap.txt | 8 + .../snap.txt | 8 + .../snap.txt | 8 + .../snap.txt | 8 + .../migration-existing-husky/snap.txt | 8 + .../snap.txt | 8 + .../snap.txt | 8 + .../snap.txt | 8 + .../snap.txt | 8 + .../migration-from-tsdown/snap.txt | 8 + .../migration-from-vitest-config/snap.txt | 8 + .../migration-from-vitest-files/snap.txt | 10 +- .../snap.txt | 8 + .../snap.txt | 8 + .../migration-husky-latest-dist-tag/snap.txt | 8 + .../migration-husky-or-prepare/snap.txt | 8 + .../snap.txt | 8 + .../snap.txt | 8 + .../migration-lint-staged-in-scripts/snap.txt | 8 + .../migration-lint-staged-merge-fail/snap.txt | 8 + .../migration-lint-staged-ts-config/snap.txt | 8 + .../migration-lintstagedrc-json/snap.txt | 8 + .../snap.txt | 8 + .../snap.txt | 8 + .../snap.txt | 8 + .../migration-merge-vite-config-js/snap.txt | 8 + .../migration-merge-vite-config-ts/snap.txt | 8 + .../migration-monorepo-bun/snap.txt | 8 +- .../snap.txt | 8 + .../migration-monorepo-pnpm/snap.txt | 8 + .../snap.txt | 4 +- .../migration-monorepo-yarn4/snap.txt | 6 +- .../migration-no-git-repo/snap.txt | 8 + .../migration-no-hooks-with-husky/snap.txt | 8 + .../migration-no-hooks/snap.txt | 8 + .../migration-other-hook-tool/snap.txt | 8 + .../snap.txt | 8 + .../migration-oxlintrc-jsonc/snap.txt | 8 + .../snap.txt | 8 + .../migration-prettier-eslint-combo/snap.txt | 8 + .../snap.txt | 8 + .../migration-prettier-lint-staged/snap.txt | 8 + .../migration-prettier-pkg-json/snap.txt | 8 + .../migration-prettier/snap.txt | 8 + .../migration-rewrite-declare-module/snap.txt | 8 + .../snap.txt | 2 +- .../migration-skip-vite-dependency/snap.txt | 12 +- .../snap.txt | 12 +- .../migration-standalone-npm/snap.txt | 4 +- .../migration-standalone-pnpm/snap.txt | 8 + .../migration-subpath/snap.txt | 8 + .../snap.txt | 8 + .../migration-vite-version/snap.txt | 8 + .../migration-vitest-peer-dep/snap.txt | 8 + .../new-vite-monorepo-bun/snap.txt | 4 + .../new-vite-monorepo/snap.txt | 8 + .../create-org-bundled-monorepo/snap.txt | 8 + 70 files changed, 700 insertions(+), 90 deletions(-) diff --git a/crates/vite_migration/src/import_rewriter.rs b/crates/vite_migration/src/import_rewriter.rs index 23d68b38bd..71fa2caec2 100644 --- a/crates/vite_migration/src/import_rewriter.rs +++ b/crates/vite_migration/src/import_rewriter.rs @@ -88,7 +88,6 @@ fix: $NEW_IMPORT /// ast-grep rules for rewriting vitest imports. /// /// This rewrites: -/// - `import { ... } from 'vitest'` → `import { ... } from 'vite-plus/test'` /// - `import { ... } from 'vitest/config'` → `import { ... } from 'vite-plus'` /// - `import { ... } from 'vitest/{name}'` → `import { ... } from 'vite-plus/test/{name}'` /// - `import { ... } from '@vitest/browser'` → `import { ... } from 'vite-plus/test/browser'` @@ -99,6 +98,14 @@ fix: $NEW_IMPORT /// - `import { ... } from '@vitest/browser-preview/{name}'` → `import { ... } from 'vite-plus/test/browser-preview/{name}'` /// - `import { ... } from '@vitest/browser-webdriverio'` → `import { ... } from 'vite-plus/test/browser-webdriverio'` /// - `import { ... } from '@vitest/browser-webdriverio/{name}'` → `import { ... } from 'vite-plus/test/browser-webdriverio/{name}'` +/// - `import { ... } from 'vite-plus/test'` → `import { ... } from 'vitest'` (reverse migration for the +/// bare-root specifier; required because `@vitest/mocker`'s static hoister hardcodes the +/// `vitest` specifier and runs before user plugins. Subpaths are intentionally preserved.) +/// +/// Note: the bare-root `'vitest'` specifier is intentionally NOT rewritten to `'vite-plus/test'` +/// any more. Migrated source must reach the upstream `vitest` module identity so that +/// `@vitest/mocker`'s hoister (which hardcodes `hoistedModule = "vitest"` and runs as part of +/// vitest's own plugin pipeline before user plugins) can intercept `vi.mock` calls. /// /// `declare module 'vitest' { ... }` (and the subpath/`@vitest/*` variants) are /// intentionally NOT rewritten — the `vite-plus/test*` subpaths are thin shims @@ -125,52 +132,52 @@ transform: by: "vite-plus" fix: $NEW_IMPORT --- -id: rewrite-vitest-import +id: rewrite-vitest-scoped-import language: TypeScript rule: pattern: $STR kind: string - regex: ^['"]vitest['"]$ + regex: ^['"]@vitest/(browser-playwright|browser-preview|browser-webdriverio|browser)(/.*)?['"]$ inside: kind: import_statement transform: NEW_IMPORT: replace: source: $STR - replace: vitest - by: "vite-plus/test" + replace: "@vitest/" + by: "vite-plus/test/" fix: $NEW_IMPORT --- -id: rewrite-vitest-scoped-import +id: rewrite-vitest-subpath-import language: TypeScript rule: pattern: $STR kind: string - regex: ^['"]@vitest/(browser-playwright|browser-preview|browser-webdriverio|browser)(/.*)?['"]$ + regex: ^['"]vitest/.+['"]$ inside: kind: import_statement transform: NEW_IMPORT: replace: source: $STR - replace: "@vitest/" + replace: vitest/ by: "vite-plus/test/" fix: $NEW_IMPORT --- -id: rewrite-vitest-subpath-import +id: rewrite-vite-plus-test-to-vitest language: TypeScript rule: pattern: $STR kind: string - regex: ^['"]vitest/.+['"]$ + regex: ^['"]vite-plus/test['"]$ inside: kind: import_statement transform: NEW_IMPORT: replace: source: $STR - replace: vitest/ - by: "vite-plus/test/" + replace: vite-plus/test + by: "vitest" fix: $NEW_IMPORT "#; @@ -265,16 +272,18 @@ static RE_REF_VITEST_CONFIG: LazyLock = LazyLock::new(|| { Regex::new(r#"^(\s*///\s*)"#).unwrap() }); -/// bare `vitest` → `vite-plus/test` -static RE_REF_VITEST: LazyLock = LazyLock::new(|| { - Regex::new(r#"^(\s*///\s*)"#).unwrap() -}); - /// `vitest/{subpath}` → `vite-plus/test/{subpath}` static RE_REF_VITEST_SUBPATH: LazyLock = LazyLock::new(|| { Regex::new(r#"^(\s*///\s*)"#).unwrap() }); +/// bare `vite-plus/test` → `vitest` (reverse migration for already-migrated sources). +/// Anchored so that only the exact root specifier matches — subpaths like +/// `vite-plus/test/browser` are intentionally preserved. +static RE_REF_VITE_PLUS_TEST: LazyLock = LazyLock::new(|| { + Regex::new(r#"^(\s*///\s*)"#).unwrap() +}); + /// `@vitest/{pkg}[/{subpath}]` → `vite-plus/test/{pkg}[/{subpath}]` /// Only matches packages and subpaths that vite-plus actually exports: /// - `@vitest/browser` → `vite-plus/test/browser` @@ -440,22 +449,26 @@ fn rewrite_reference_types(content: &mut String, skip_packages: &SkipPackages) - } // Each line matches at most one pattern; use early exit to skip remaining regexes. if !skip_packages.skip_vitest { - if apply_regex_replace(line, &RE_REF_VITEST_CONFIG, "${1}vite-plus${2}") { + // Reverse migration: bare `vite-plus/test` → `vitest`. Anchored so that + // subpaths like `vite-plus/test/browser` are preserved. + if apply_regex_replace(line, &RE_REF_VITE_PLUS_TEST, "${1}vitest${2}") { changed = true; continue; } - if apply_regex_replace(line, &RE_REF_VITEST_SCOPED, "${1}vite-plus/test/${2}${3}") { + if apply_regex_replace(line, &RE_REF_VITEST_CONFIG, "${1}vite-plus${2}") { changed = true; continue; } - if apply_regex_replace(line, &RE_REF_VITEST_SUBPATH, "${1}vite-plus/test/${2}${3}") { + if apply_regex_replace(line, &RE_REF_VITEST_SCOPED, "${1}vite-plus/test/${2}${3}") { changed = true; continue; } - if apply_regex_replace(line, &RE_REF_VITEST, "${1}vite-plus/test${2}") { + if apply_regex_replace(line, &RE_REF_VITEST_SUBPATH, "${1}vite-plus/test/${2}${3}") { changed = true; continue; } + // The bare `vitest` triple-slash reference is intentionally left alone — see + // the note on `REWRITE_VITEST_RULES` above. } if !skip_packages.skip_vite { if apply_regex_replace(line, &RE_REF_VITE_SUBPATH, "${1}vite-plus/${2}${3}") { @@ -914,6 +927,9 @@ export default defineConfig({ #[test] fn test_rewrite_import_content_vitest() { + // Bare `vitest` is intentionally left untouched: vite-plus's runtime + // canonical specifier is `vitest`, and `@vitest/mocker`'s static hoister + // hardcodes that specifier and must see it unchanged. let vite_config = r#"import { describe, it, expect } from 'vitest'; describe('test', () => { @@ -923,33 +939,20 @@ describe('test', () => { });"#; let result = rewrite_import_content(vite_config, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"import { describe, it, expect } from 'vite-plus/test'; - -describe('test', () => { - it('should work', () => { - expect(true).toBe(true); - }); -});"# - ); + assert!(!result.updated); + assert_eq!(result.content, vite_config); } #[test] fn test_rewrite_import_content_vitest_double_quotes() { + // See note on `test_rewrite_import_content_vitest`: bare `vitest` is preserved. let vite_config = r#"import { describe, it, expect } from "vitest"; describe('test', () => {});"#; let result = rewrite_import_content(vite_config, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"import { describe, it, expect } from "vite-plus/test"; - -describe('test', () => {});"# - ); + assert!(!result.updated); + assert_eq!(result.content, vite_config); } #[test] @@ -1212,7 +1215,7 @@ export default defineConfig({ result.content, r#"import { defineConfig } from 'vite-plus'; import { ModuleRunner } from 'vite-plus/module-runner'; -import { describe, it, expect } from 'vite-plus/test'; +import { describe, it, expect } from 'vitest'; import { startVitest } from 'vite-plus/test/node'; import { page } from 'vite-plus/test/browser'; import { playwright } from 'vite-plus/test/browser-playwright'; @@ -1241,9 +1244,11 @@ export default defineConfig({});"#, ) .unwrap(); + // A previously-migrated source file with `vite-plus/test` — the migrator + // should reverse it back to `vitest`. fs::write( temp.path().join("src/test.ts"), - r#"import { describe, it } from 'vitest'; + r#"import { describe, it } from 'vite-plus/test'; describe('test', () => {});"#, ) .unwrap(); @@ -1283,7 +1288,8 @@ describe('test', () => {});"#, assert!(config_content.contains("vite-plus")); let test_content = fs::read_to_string(temp.path().join("src/test.ts")).unwrap(); - assert!(test_content.contains("vite-plus/test")); + assert!(test_content.contains("from 'vitest'")); + assert!(!test_content.contains("vite-plus/test")); // Verify utils.ts was not modified let utils_content = fs::read_to_string(temp.path().join("src/utils.ts")).unwrap(); @@ -1567,7 +1573,7 @@ export default defineConfig({});"#; assert_eq!( result.content, r#"import { defineConfig } from 'vite-plus'; -import { describe } from 'vite-plus/test'; +import { describe } from 'vitest'; declare module 'vite-plus' { interface UserConfig { @@ -1900,9 +1906,12 @@ export default defineConfig({ #[test] fn test_skip_vite_when_peer_dependency() { - // When vite is a peerDependency, vite imports should NOT be rewritten + // When vite is a peerDependency, vite imports should NOT be rewritten. + // The vitest import is the canonical specifier and is also preserved as-is — + // exercise the reverse-migration path by including a `vite-plus/test` import. let content = r#"import { defineConfig } from 'vite'; import { describe } from 'vitest'; +import { vi } from 'vite-plus/test'; export default defineConfig({});"#; @@ -1911,11 +1920,13 @@ export default defineConfig({});"#; let result = rewrite_import_content(content, &skip_packages).unwrap(); assert!(result.updated); - // vite import should NOT be rewritten, vitest import SHOULD be rewritten + // vite import should NOT be rewritten; vitest import already canonical; + // vite-plus/test should be reverse-migrated to vitest. assert_eq!( result.content, r#"import { defineConfig } from 'vite'; -import { describe } from 'vite-plus/test'; +import { describe } from 'vitest'; +import { vi } from 'vitest'; export default defineConfig({});"# ); @@ -2114,9 +2125,10 @@ export default defineConfig({});"#; // Create src directory fs::create_dir(temp.path().join("src")).unwrap(); - // Create source file with vite and vitest imports + // Create source file with vite import (preserved because vite is a dep) + // and a previously-migrated `vite-plus/test` import (must be reverse-migrated). let original_content = r#"import { defineConfig } from 'vite'; -import { describe } from 'vitest'; +import { vi } from 'vite-plus/test'; export default defineConfig({});"#; fs::write(temp.path().join("src/index.ts"), original_content).unwrap(); @@ -2124,16 +2136,16 @@ export default defineConfig({});"#; // Run the batch rewrite let result = rewrite_imports_in_directory(temp.path()).unwrap(); - // File should be modified (vitest was rewritten) + // File should be modified (vite-plus/test was reverse-migrated) assert_eq!(result.modified_files.len(), 1); assert!(result.errors.is_empty()); - // Verify vite import NOT rewritten (in dependencies), vitest IS rewritten + // Verify vite import NOT rewritten (in dependencies), vite-plus/test IS reverse-rewritten let content = fs::read_to_string(temp.path().join("src/index.ts")).unwrap(); assert_eq!( content, r#"import { defineConfig } from 'vite'; -import { describe } from 'vite-plus/test'; +import { vi } from 'vitest'; export default defineConfig({});"# ); @@ -2157,9 +2169,10 @@ export default defineConfig({});"# // Create src directory fs::create_dir(temp.path().join("src")).unwrap(); - // Create source file with vite and vitest imports + // Create source file with vite import (preserved because vite is peerDep) + // and a previously-migrated `vite-plus/test` import (must be reverse-migrated). let original_content = r#"import { defineConfig } from 'vite'; -import { describe } from 'vitest'; +import { vi } from 'vite-plus/test'; export default defineConfig({});"#; fs::write(temp.path().join("src/index.ts"), original_content).unwrap(); @@ -2167,16 +2180,16 @@ export default defineConfig({});"#; // Run the batch rewrite let result = rewrite_imports_in_directory(temp.path()).unwrap(); - // File should be modified (vitest was rewritten) + // File should be modified (vite-plus/test was reverse-migrated) assert_eq!(result.modified_files.len(), 1); assert!(result.errors.is_empty()); - // Verify vite import NOT rewritten, vitest IS rewritten + // Verify vite import NOT rewritten, vite-plus/test IS reverse-rewritten let content = fs::read_to_string(temp.path().join("src/index.ts")).unwrap(); assert_eq!( content, r#"import { defineConfig } from 'vite'; -import { describe } from 'vite-plus/test'; +import { vi } from 'vitest'; export default defineConfig({});"# ); @@ -2279,20 +2292,22 @@ import { build } from 'tsdown';"#; // app package.json (no peerDeps) fs::write(temp.path().join("packages/app/package.json"), r#"{"name": "app"}"#).unwrap(); - // vite-plugin source file with vite and vitest imports + // vite-plugin source file: vite import preserved (peerDep) and a + // previously-migrated `vite-plus/test` import that needs reverse-migration. fs::write( temp.path().join("packages/vite-plugin/src/index.ts"), r#"import { defineConfig } from 'vite'; -import { describe } from 'vitest'; +import { vi } from 'vite-plus/test'; export default defineConfig({});"#, ) .unwrap(); - // app source file with vite and vitest imports + // app source file: vite import (will be rewritten) and a previously-migrated + // `vite-plus/test` import (must be reverse-migrated). fs::write( temp.path().join("packages/app/src/index.ts"), r#"import { defineConfig } from 'vite'; -import { describe } from 'vitest'; +import { vi } from 'vite-plus/test'; export default defineConfig({});"#, ) .unwrap(); @@ -2303,23 +2318,23 @@ export default defineConfig({});"#, // Both files should be modified assert_eq!(result.modified_files.len(), 2); - // vite-plugin: vite NOT rewritten (has peerDep), vitest IS rewritten + // vite-plugin: vite NOT rewritten (has peerDep), vite-plus/test reverse-migrated let vite_plugin_content = fs::read_to_string(temp.path().join("packages/vite-plugin/src/index.ts")).unwrap(); assert_eq!( vite_plugin_content, r#"import { defineConfig } from 'vite'; -import { describe } from 'vite-plus/test'; +import { vi } from 'vitest'; export default defineConfig({});"# ); - // app: vite IS rewritten (no peerDep), vitest IS rewritten + // app: vite IS rewritten (no peerDep), vite-plus/test reverse-migrated let app_content = fs::read_to_string(temp.path().join("packages/app/src/index.ts")).unwrap(); assert_eq!( app_content, r#"import { defineConfig } from 'vite-plus'; -import { describe } from 'vite-plus/test'; +import { vi } from 'vitest'; export default defineConfig({});"# ); } @@ -2354,10 +2369,12 @@ export default defineConfig({});"# #[test] fn test_rewrite_reference_types_bare_vitest() { + // Bare `vitest` triple-slash reference is intentionally preserved: see + // the `REWRITE_VITEST_RULES` note. The canonical specifier is `vitest`. let content = r#"/// "#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!(result.content, r#"/// "#); + assert!(!result.updated); + assert_eq!(result.content, content); } #[test] @@ -2499,14 +2516,15 @@ const x = 1; #[test] fn test_rewrite_reference_types_after_multiline_block_comment() { - // Multi-line block comments should be skipped entirely + // Multi-line block comments should be skipped entirely. Use `vite-plus/test` + // so the reverse-migration rule fires and we still observe a rewrite. let content = - "/*\n * License header\n * Copyright 2024\n */\n/// \n"; + "/*\n * License header\n * Copyright 2024\n */\n/// \n"; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); assert!(result.updated); assert_eq!( result.content, - "/*\n * License header\n * Copyright 2024\n */\n/// \n" + "/*\n * License header\n * Copyright 2024\n */\n/// \n" ); } @@ -2599,14 +2617,15 @@ const x = 1; #[test] fn test_rewrite_reference_types_crlf() { - // CRLF line endings should be preserved + // CRLF line endings should be preserved. Use a `vite-plus/test` reference + // so the reverse-migration rule fires on the second line. let content = - "/// \r\n/// \r\n"; + "/// \r\n/// \r\n"; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); assert!(result.updated); assert_eq!( result.content, - "/// \r\n/// \r\n" + "/// \r\n/// \r\n" ); } @@ -2698,8 +2717,10 @@ const x = 1; #[test] fn test_rewrite_reference_types_env_d_ts_style() { + // Bare `vitest` is intentionally preserved (canonical specifier). + // Use `vite-plus/test` instead to exercise the reverse-migration rule. let content = r#"/// -/// +/// /// /// /// "#; @@ -2709,7 +2730,7 @@ const x = 1; assert_eq!( result.content, r#"/// -/// +/// /// /// /// "# @@ -2736,8 +2757,11 @@ export default defineConfig({});"# #[test] fn test_rewrite_reference_types_skip_vite() { + // With vite skipped, only the vitest reference is processed. Use `vite-plus/test` + // (the deprecated specifier) so the reverse-migration rule fires; bare `vitest` + // is preserved as the canonical specifier. let content = r#"/// -/// "#; +/// "#; let skip_packages = SkipPackages { skip_vite: true, skip_vitest: false, skip_tsdown: false }; @@ -2746,7 +2770,7 @@ export default defineConfig({});"# assert_eq!( result.content, r#"/// -/// "# +/// "# ); } @@ -2795,4 +2819,88 @@ export default defineConfig({});"# assert!(!result.updated); assert_eq!(result.content, content); } + + #[test] + fn test_rewrite_import_content_vite_plus_test_to_vitest() { + // Reverse migration: a previously-migrated source that still has + // `from 'vite-plus/test'` must be rewritten back to `from 'vitest'`, + // because `@vitest/mocker`'s static hoister hardcodes the `vitest` + // specifier and runs before user plugins. + let source = r#"import { vi, describe, it } from 'vite-plus/test'; + +describe('mock', () => { + vi.mock('./dep'); +});"#; + + let result = rewrite_import_content(source, &SkipPackages::default()).unwrap(); + assert!(result.updated); + assert_eq!( + result.content, + r#"import { vi, describe, it } from 'vitest'; + +describe('mock', () => { + vi.mock('./dep'); +});"# + ); + } + + #[test] + fn test_rewrite_import_content_vite_plus_test_double_quotes_to_vitest() { + let source = r#"import { vi } from "vite-plus/test"; + +vi.mock("./dep");"#; + + let result = rewrite_import_content(source, &SkipPackages::default()).unwrap(); + assert!(result.updated); + assert_eq!( + result.content, + r#"import { vi } from "vitest"; + +vi.mock("./dep");"# + ); + } + + #[test] + fn test_rewrite_import_content_vite_plus_test_subpath_preserved() { + // Subpaths under `vite-plus/test` are vite-plus exports (shims for the + // browser provider packages) and MUST NOT be reverse-rewritten. + let source = r#"import { playwright } from 'vite-plus/test/browser-playwright'; +import { page } from 'vite-plus/test/browser'; + +export { playwright, page };"#; + + let result = rewrite_import_content(source, &SkipPackages::default()).unwrap(); + assert!(!result.updated); + assert_eq!(result.content, source); + } + + #[test] + fn test_rewrite_reference_types_vite_plus_test_to_vitest() { + // Reverse-direction triple-slash reference rewrite: bare root only. + let content = r#"/// "#; + let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); + assert!(result.updated); + assert_eq!(result.content, r#"/// "#); + } + + #[test] + fn test_rewrite_reference_types_vite_plus_test_subpath_preserved() { + // Subpaths under `vite-plus/test` map to dedicated vite-plus exports + // and must not be rewritten back to `@vitest/*`. + let content = r#"/// "#; + let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); + assert!(!result.updated); + assert_eq!(result.content, content); + } + + #[test] + fn test_rewrite_import_content_vite_plus_test_skipped_when_vitest_skipped() { + // When the package declares `vitest` as a dep/peerDep, no vitest-family + // rewrites should fire — including the reverse one. + let source = r#"import { vi } from 'vite-plus/test';"#; + let skip = SkipPackages { skip_vite: false, skip_vitest: true, skip_tsdown: false }; + let result = rewrite_import_content(source, &skip).unwrap(); + assert!(!result.updated); + assert_eq!(result.content, source); + } } diff --git a/packages/cli/snap-tests-global/command-list-pnpm10-with-workspace/snap.txt b/packages/cli/snap-tests-global/command-list-pnpm10-with-workspace/snap.txt index 8b3872dce4..54ebf902c2 100644 --- a/packages/cli/snap-tests-global/command-list-pnpm10-with-workspace/snap.txt +++ b/packages/cli/snap-tests-global/command-list-pnpm10-with-workspace/snap.txt @@ -1,6 +1,6 @@ > vp install # should install packages first Scope: all workspace projects -Packages: + +  Packages: + + Progress: resolved , reused , downloaded , added , done diff --git a/packages/cli/snap-tests-global/command-outdated-pnpm10/snap.txt b/packages/cli/snap-tests-global/command-outdated-pnpm10/snap.txt index ec085ee577..532cd5ed1e 100644 --- a/packages/cli/snap-tests-global/command-outdated-pnpm10/snap.txt +++ b/packages/cli/snap-tests-global/command-outdated-pnpm10/snap.txt @@ -145,7 +145,7 @@ testnpm2 └──────────────────────────────────┴─────────┴────────┘ [1]> vp outdated --no-optional # should support no-optional output -┌──────────────────────────────────┬─────────┬────────┐ +  ┌──────────────────────────────────┬─────────┬────────┐ │ Package │ Current │ Latest │ ├──────────────────────────────────┼─────────┼────────┤ │ testnpm2 │ │ diff --git a/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt b/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt index 4ce77e95a1..d7cc58178d 100644 --- a/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,6 +67,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat .vite-hooks/pre-commit # check pre-commit hook vp staged diff --git a/packages/cli/snap-tests-global/migration-auto-create-vite-config/snap.txt b/packages/cli/snap-tests-global/migration-auto-create-vite-config/snap.txt index 18f8b6437e..7150561501 100644 --- a/packages/cli/snap-tests-global/migration-auto-create-vite-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-auto-create-vite-config/snap.txt @@ -59,6 +59,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -70,6 +72,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -81,6 +85,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -91,3 +97,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-baseurl-tsconfig/snap.txt b/packages/cli/snap-tests-global/migration-baseurl-tsconfig/snap.txt index fca4177b80..84956946ea 100644 --- a/packages/cli/snap-tests-global/migration-baseurl-tsconfig/snap.txt +++ b/packages/cli/snap-tests-global/migration-baseurl-tsconfig/snap.txt @@ -52,6 +52,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -63,6 +65,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -74,6 +78,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -84,3 +90,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-chained-lint-staged-pre-commit/snap.txt b/packages/cli/snap-tests-global/migration-chained-lint-staged-pre-commit/snap.txt index a17217d5d2..7522a22436 100644 --- a/packages/cli/snap-tests-global/migration-chained-lint-staged-pre-commit/snap.txt +++ b/packages/cli/snap-tests-global/migration-chained-lint-staged-pre-commit/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,6 +67,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt b/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt index be31c8cb64..0045a275f7 100644 --- a/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt +++ b/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,6 +67,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat .config/husky/pre-commit # pre-commit hook should be in custom dir vp staged diff --git a/packages/cli/snap-tests-global/migration-composed-husky-prepare/snap.txt b/packages/cli/snap-tests-global/migration-composed-husky-prepare/snap.txt index b39bd11c8b..9449c4f80b 100644 --- a/packages/cli/snap-tests-global/migration-composed-husky-prepare/snap.txt +++ b/packages/cli/snap-tests-global/migration-composed-husky-prepare/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,3 +67,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-env-prefix-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-env-prefix-lint-staged/snap.txt index d5813a49c0..c8494ebce7 100644 --- a/packages/cli/snap-tests-global/migration-env-prefix-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-env-prefix-lint-staged/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,6 +67,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-eslint-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-eslint-lint-staged/snap.txt index 2303b04524..a4bad90173 100644 --- a/packages/cli/snap-tests-global/migration-eslint-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-eslint-lint-staged/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,6 +67,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat vite.config.ts # check oxlint config and staged config merged into vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-eslint-lintstagedrc/snap.txt b/packages/cli/snap-tests-global/migration-eslint-lintstagedrc/snap.txt index 497e2a08c2..c267a1c475 100644 --- a/packages/cli/snap-tests-global/migration-eslint-lintstagedrc/snap.txt +++ b/packages/cli/snap-tests-global/migration-eslint-lintstagedrc/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,6 +67,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > test ! -f .lintstagedrc.json # check lintstagedrc.json is removed > cat vite.config.ts # check oxlint config merged into vite.config.ts diff --git a/packages/cli/snap-tests-global/migration-eslint-npx-wrapper/snap.txt b/packages/cli/snap-tests-global/migration-eslint-npx-wrapper/snap.txt index 3664be6ff3..6a34937308 100644 --- a/packages/cli/snap-tests-global/migration-eslint-npx-wrapper/snap.txt +++ b/packages/cli/snap-tests-global/migration-eslint-npx-wrapper/snap.txt @@ -34,6 +34,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -45,6 +47,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -56,6 +60,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -66,5 +72,7 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > test ! -f eslint.config.mjs # check eslint config is removed \ No newline at end of file diff --git a/packages/cli/snap-tests-global/migration-eslint/snap.txt b/packages/cli/snap-tests-global/migration-eslint/snap.txt index 0b9f35fdb4..a63e323bbe 100644 --- a/packages/cli/snap-tests-global/migration-eslint/snap.txt +++ b/packages/cli/snap-tests-global/migration-eslint/snap.txt @@ -32,6 +32,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -43,6 +45,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -54,6 +58,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -64,6 +70,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > test ! -f eslint.config.mjs # check eslint config is removed > cat vite.config.ts # check oxlint config merged into vite.config.ts diff --git a/packages/cli/snap-tests-global/migration-existing-husky-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-existing-husky-lint-staged/snap.txt index 5cedf9a5a0..d9119ace3e 100644 --- a/packages/cli/snap-tests-global/migration-existing-husky-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-husky-lint-staged/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,6 +67,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-existing-husky-v8-hooks/snap.txt b/packages/cli/snap-tests-global/migration-existing-husky-v8-hooks/snap.txt index 5579ee2e03..a99de01fd3 100644 --- a/packages/cli/snap-tests-global/migration-existing-husky-v8-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-husky-v8-hooks/snap.txt @@ -32,6 +32,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -43,6 +45,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -54,6 +58,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -64,6 +70,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat .husky/pre-commit # hook file should be unchanged (still has bootstrap) . "$(dirname -- "$0")/_/husky.sh" diff --git a/packages/cli/snap-tests-global/migration-existing-husky-v8-multi-hooks/snap.txt b/packages/cli/snap-tests-global/migration-existing-husky-v8-multi-hooks/snap.txt index 3c372f31d2..c7fdd12381 100644 --- a/packages/cli/snap-tests-global/migration-existing-husky-v8-multi-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-husky-v8-multi-hooks/snap.txt @@ -32,6 +32,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -43,6 +45,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -54,6 +58,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -64,6 +70,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat .husky/pre-commit # hook file should be unchanged (still has bootstrap) . "$(dirname -- "$0")/_/husky.sh" diff --git a/packages/cli/snap-tests-global/migration-existing-husky/snap.txt b/packages/cli/snap-tests-global/migration-existing-husky/snap.txt index 7426c9a704..d12d519cac 100644 --- a/packages/cli/snap-tests-global/migration-existing-husky/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-husky/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,6 +67,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat .vite-hooks/pre-commit # check pre-commit hook rewritten to vp staged vp staged diff --git a/packages/cli/snap-tests-global/migration-existing-lint-staged-config/snap.txt b/packages/cli/snap-tests-global/migration-existing-lint-staged-config/snap.txt index 1993658615..dabfa69415 100644 --- a/packages/cli/snap-tests-global/migration-existing-lint-staged-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-lint-staged-config/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,6 +67,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > test ! -f .lintstagedrc.json # check lintstagedrc.json (should be deleted after inlining to vite.config.ts) > cat vite.config.ts # check staged config migrated to vite.config.ts diff --git a/packages/cli/snap-tests-global/migration-existing-pnpm-exec-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-existing-pnpm-exec-lint-staged/snap.txt index b4d996f03b..2594f21fe1 100644 --- a/packages/cli/snap-tests-global/migration-existing-pnpm-exec-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-pnpm-exec-lint-staged/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,6 +67,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-existing-prepare-script/snap.txt b/packages/cli/snap-tests-global/migration-existing-prepare-script/snap.txt index 9f62ab7d36..04fd212766 100644 --- a/packages/cli/snap-tests-global/migration-existing-prepare-script/snap.txt +++ b/packages/cli/snap-tests-global/migration-existing-prepare-script/snap.txt @@ -30,6 +30,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -41,6 +43,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -52,6 +56,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -62,6 +68,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat .vite-hooks/pre-commit # check pre-commit hook vp staged diff --git a/packages/cli/snap-tests-global/migration-from-tsdown-json-config/snap.txt b/packages/cli/snap-tests-global/migration-from-tsdown-json-config/snap.txt index 02968f1686..78cd8c5d9e 100644 --- a/packages/cli/snap-tests-global/migration-from-tsdown-json-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-tsdown-json-config/snap.txt @@ -54,6 +54,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -65,6 +67,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -76,6 +80,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -86,6 +92,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > vp migrate --no-interactive # run migration again to check if it is idempotent This project is already using Vite+! Happy coding! diff --git a/packages/cli/snap-tests-global/migration-from-tsdown/snap.txt b/packages/cli/snap-tests-global/migration-from-tsdown/snap.txt index 67c649f122..519fc06549 100644 --- a/packages/cli/snap-tests-global/migration-from-tsdown/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-tsdown/snap.txt @@ -56,6 +56,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -67,6 +69,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -78,6 +82,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -88,6 +94,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > vp migrate --no-interactive # run migration again to check if it is idempotent This project is already using Vite+! Happy coding! diff --git a/packages/cli/snap-tests-global/migration-from-vitest-config/snap.txt b/packages/cli/snap-tests-global/migration-from-vitest-config/snap.txt index fc0d2d0201..1ba1a5b5b1 100644 --- a/packages/cli/snap-tests-global/migration-from-vitest-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-vitest-config/snap.txt @@ -59,6 +59,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -70,6 +72,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -81,6 +85,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -91,3 +97,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt b/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt index a416b1a6b2..345c9bbdf5 100644 --- a/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt @@ -34,6 +34,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -45,6 +47,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -56,6 +60,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -66,10 +72,12 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat test/hello.ts # check test/hello.ts import { server } from 'vite-plus/test/browser-playwright/context'; -import { test, describe, expect, it } from 'vite-plus/test'; +import { test, describe, expect, it } from 'vitest'; const { readFile } = server.commands; diff --git a/packages/cli/snap-tests-global/migration-hooks-skip-on-existing-hookspath/snap.txt b/packages/cli/snap-tests-global/migration-hooks-skip-on-existing-hookspath/snap.txt index 5e1f59ac47..8a68364d50 100644 --- a/packages/cli/snap-tests-global/migration-hooks-skip-on-existing-hookspath/snap.txt +++ b/packages/cli/snap-tests-global/migration-hooks-skip-on-existing-hookspath/snap.txt @@ -32,6 +32,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -43,6 +45,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -54,6 +58,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -64,6 +70,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > git config --local core.hooksPath # should still be .custom-hooks .custom-hooks diff --git a/packages/cli/snap-tests-global/migration-husky-latest-dist-tag-v9-installed/snap.txt b/packages/cli/snap-tests-global/migration-husky-latest-dist-tag-v9-installed/snap.txt index b7d4ba2e63..a206964bed 100644 --- a/packages/cli/snap-tests-global/migration-husky-latest-dist-tag-v9-installed/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-latest-dist-tag-v9-installed/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,3 +67,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-husky-latest-dist-tag/snap.txt b/packages/cli/snap-tests-global/migration-husky-latest-dist-tag/snap.txt index cfe0fdc9b5..24da13436e 100644 --- a/packages/cli/snap-tests-global/migration-husky-latest-dist-tag/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-latest-dist-tag/snap.txt @@ -31,6 +31,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -42,6 +44,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -53,6 +57,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -63,3 +69,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-husky-or-prepare/snap.txt b/packages/cli/snap-tests-global/migration-husky-or-prepare/snap.txt index c7b648d8ce..5ed837570a 100644 --- a/packages/cli/snap-tests-global/migration-husky-or-prepare/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-or-prepare/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,3 +67,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-husky-semicolon-prepare/snap.txt b/packages/cli/snap-tests-global/migration-husky-semicolon-prepare/snap.txt index 6a5361aa75..8bedb4f985 100644 --- a/packages/cli/snap-tests-global/migration-husky-semicolon-prepare/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-semicolon-prepare/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,3 +67,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-husky-v8-preserves-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-husky-v8-preserves-lint-staged/snap.txt index aa7f9631f9..a774cb3326 100644 --- a/packages/cli/snap-tests-global/migration-husky-v8-preserves-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-husky-v8-preserves-lint-staged/snap.txt @@ -35,6 +35,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -46,6 +48,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -57,6 +61,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -67,3 +73,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-lint-staged-in-scripts/snap.txt b/packages/cli/snap-tests-global/migration-lint-staged-in-scripts/snap.txt index 24b70595ad..aa182bb13f 100644 --- a/packages/cli/snap-tests-global/migration-lint-staged-in-scripts/snap.txt +++ b/packages/cli/snap-tests-global/migration-lint-staged-in-scripts/snap.txt @@ -30,6 +30,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -41,6 +43,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -52,6 +56,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -62,6 +68,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-lint-staged-merge-fail/snap.txt b/packages/cli/snap-tests-global/migration-lint-staged-merge-fail/snap.txt index 86f1c47acf..690f787b31 100644 --- a/packages/cli/snap-tests-global/migration-lint-staged-merge-fail/snap.txt +++ b/packages/cli/snap-tests-global/migration-lint-staged-merge-fail/snap.txt @@ -38,6 +38,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -49,6 +51,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -60,6 +64,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -70,6 +76,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat vite.config.ts # vite config should be unchanged (merge failed) const config = { plugins: [] }; diff --git a/packages/cli/snap-tests-global/migration-lint-staged-ts-config/snap.txt b/packages/cli/snap-tests-global/migration-lint-staged-ts-config/snap.txt index 2680b69695..6ba1c88d88 100644 --- a/packages/cli/snap-tests-global/migration-lint-staged-ts-config/snap.txt +++ b/packages/cli/snap-tests-global/migration-lint-staged-ts-config/snap.txt @@ -33,6 +33,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -44,6 +46,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -55,6 +59,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -65,6 +71,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat lint-staged.config.ts # check TS config is not modified export default { diff --git a/packages/cli/snap-tests-global/migration-lintstagedrc-json/snap.txt b/packages/cli/snap-tests-global/migration-lintstagedrc-json/snap.txt index 2391a2b7dc..3d2323f246 100644 --- a/packages/cli/snap-tests-global/migration-lintstagedrc-json/snap.txt +++ b/packages/cli/snap-tests-global/migration-lintstagedrc-json/snap.txt @@ -101,6 +101,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -112,6 +114,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -123,6 +127,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -133,6 +139,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat vite.config.ts # check staged config migrated to vite.config.ts import { defineConfig } from 'vite-plus'; diff --git a/packages/cli/snap-tests-global/migration-lintstagedrc-merge-fail/snap.txt b/packages/cli/snap-tests-global/migration-lintstagedrc-merge-fail/snap.txt index 599bd04ca2..93995ebc9e 100644 --- a/packages/cli/snap-tests-global/migration-lintstagedrc-merge-fail/snap.txt +++ b/packages/cli/snap-tests-global/migration-lintstagedrc-merge-fail/snap.txt @@ -35,6 +35,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -46,6 +48,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -57,6 +61,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -67,6 +73,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat .lintstagedrc.json # config file should be preserved when merge fails { diff --git a/packages/cli/snap-tests-global/migration-lintstagedrc-not-support/snap.txt b/packages/cli/snap-tests-global/migration-lintstagedrc-not-support/snap.txt index 796b4958dc..bee3bf5eb6 100644 --- a/packages/cli/snap-tests-global/migration-lintstagedrc-not-support/snap.txt +++ b/packages/cli/snap-tests-global/migration-lintstagedrc-not-support/snap.txt @@ -46,6 +46,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -57,6 +59,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -68,6 +72,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -78,3 +84,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-lintstagedrc-staged-exists/snap.txt b/packages/cli/snap-tests-global/migration-lintstagedrc-staged-exists/snap.txt index ffa874eb58..dd57b74f98 100644 --- a/packages/cli/snap-tests-global/migration-lintstagedrc-staged-exists/snap.txt +++ b/packages/cli/snap-tests-global/migration-lintstagedrc-staged-exists/snap.txt @@ -30,6 +30,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -41,6 +43,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -52,6 +56,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -62,6 +68,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > test -f .lintstagedrc.json && echo 'lintstagedrc.json still exists' || echo 'lintstagedrc.json was deleted' # should still exist lintstagedrc.json still exists diff --git a/packages/cli/snap-tests-global/migration-merge-vite-config-js/snap.txt b/packages/cli/snap-tests-global/migration-merge-vite-config-js/snap.txt index 32d1a7a32a..eab8772149 100644 --- a/packages/cli/snap-tests-global/migration-merge-vite-config-js/snap.txt +++ b/packages/cli/snap-tests-global/migration-merge-vite-config-js/snap.txt @@ -58,6 +58,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -69,6 +71,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -80,6 +84,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -90,3 +96,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-merge-vite-config-ts/snap.txt b/packages/cli/snap-tests-global/migration-merge-vite-config-ts/snap.txt index c7143d6230..fd657cd36c 100644 --- a/packages/cli/snap-tests-global/migration-merge-vite-config-ts/snap.txt +++ b/packages/cli/snap-tests-global/migration-merge-vite-config-ts/snap.txt @@ -92,6 +92,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -103,6 +105,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -114,6 +118,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -124,3 +130,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-monorepo-bun/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-bun/snap.txt index df11dc19f1..732fdbbbc1 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-bun/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-bun/snap.txt @@ -52,7 +52,9 @@ export default defineConfig({ "@vitest/spy": "4.1.5", "@vitest/utils": "4.1.5", "@vitest/mocker": "4.1.5", - "@vitest/pretty-format": "4.1.5" + "@vitest/pretty-format": "4.1.5", + "@vitest/coverage-v8": "4.1.5", + "@vitest/coverage-istanbul": "4.1.5" } }, "scripts": { @@ -82,7 +84,9 @@ export default defineConfig({ "@vitest/spy": "catalog:", "@vitest/utils": "catalog:", "@vitest/mocker": "catalog:", - "@vitest/pretty-format": "catalog:" + "@vitest/pretty-format": "catalog:", + "@vitest/coverage-v8": "catalog:", + "@vitest/coverage-istanbul": "catalog:" } } diff --git a/packages/cli/snap-tests-global/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt index 56aff278e7..53597bbc03 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-pnpm-overrides-dependency-selector/snap.txt @@ -46,6 +46,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: @@ -60,6 +62,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' react-click-away-listener>react: peerDependencyRules: allowAny: @@ -72,6 +76,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -82,6 +88,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat packages/app/package.json # check app package.json { diff --git a/packages/cli/snap-tests-global/migration-monorepo-pnpm/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-pnpm/snap.txt index ac0588056f..5c92ec6d21 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-pnpm/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-pnpm/snap.txt @@ -90,6 +90,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest minimumReleaseAge: 1440 @@ -103,6 +105,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -114,6 +118,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -124,6 +130,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' minimumReleaseAgeExclude: - vite-plus - '@voidzero-dev/*' diff --git a/packages/cli/snap-tests-global/migration-monorepo-skip-vite-peer-dependency/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-skip-vite-peer-dependency/snap.txt index dfe73cacba..5ed3e43cc0 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-skip-vite-peer-dependency/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-skip-vite-peer-dependency/snap.txt @@ -1,11 +1,11 @@ > vp migrate --no-interactive # migration should preserve vite peer contracts in workspace packages ◇ Migrated . to Vite+ • Node pnpm -• 2 config updates applied, 1 file had imports rewritten +• 2 config updates applied > cat packages/vite-plugin/src/index.ts # vite-plugin has vite in peerDeps: vite imports stay public, vitest rewrites import { defineConfig, type Plugin } from 'vite'; -import { describe, it, expect } from 'vite-plus/test'; +import { describe, it, expect } from 'vitest'; export function myVitePlugin(): Plugin { return { diff --git a/packages/cli/snap-tests-global/migration-monorepo-yarn4/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-yarn4/snap.txt index f4ac551e9a..cba4c95cb6 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-yarn4/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-yarn4/snap.txt @@ -72,7 +72,9 @@ export default defineConfig({ "@vitest/spy": "4.1.5", "@vitest/utils": "4.1.5", "@vitest/mocker": "4.1.5", - "@vitest/pretty-format": "4.1.5" + "@vitest/pretty-format": "4.1.5", + "@vitest/coverage-v8": "4.1.5", + "@vitest/coverage-istanbul": "4.1.5" } } @@ -88,6 +90,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest > cat packages/app/package.json # check app package.json diff --git a/packages/cli/snap-tests-global/migration-no-git-repo/snap.txt b/packages/cli/snap-tests-global/migration-no-git-repo/snap.txt index c4f5c6fe68..9afdb35823 100644 --- a/packages/cli/snap-tests-global/migration-no-git-repo/snap.txt +++ b/packages/cli/snap-tests-global/migration-no-git-repo/snap.txt @@ -27,6 +27,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -38,6 +40,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -49,6 +53,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -59,6 +65,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > test -d .vite-hooks && echo 'hooks dir exists' || echo 'no hooks dir' hooks dir exists diff --git a/packages/cli/snap-tests-global/migration-no-hooks-with-husky/snap.txt b/packages/cli/snap-tests-global/migration-no-hooks-with-husky/snap.txt index 391bc745f3..8b823c5f5d 100644 --- a/packages/cli/snap-tests-global/migration-no-hooks-with-husky/snap.txt +++ b/packages/cli/snap-tests-global/migration-no-hooks-with-husky/snap.txt @@ -34,6 +34,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -45,6 +47,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -56,6 +60,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -66,6 +72,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > test -d .husky && echo '.husky directory exists' || echo 'No .husky directory' # verify no .husky directory No .husky directory diff --git a/packages/cli/snap-tests-global/migration-no-hooks/snap.txt b/packages/cli/snap-tests-global/migration-no-hooks/snap.txt index 6be606bdce..2f04ba4e65 100644 --- a/packages/cli/snap-tests-global/migration-no-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-no-hooks/snap.txt @@ -25,6 +25,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -36,6 +38,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -47,6 +51,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -57,6 +63,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > test -d .vite-hooks && echo '.vite-hooks directory exists' || echo 'No .vite-hooks directory' # verify no .vite-hooks directory No .vite-hooks directory diff --git a/packages/cli/snap-tests-global/migration-other-hook-tool/snap.txt b/packages/cli/snap-tests-global/migration-other-hook-tool/snap.txt index 6ac820c0b5..e6ed2a66c4 100644 --- a/packages/cli/snap-tests-global/migration-other-hook-tool/snap.txt +++ b/packages/cli/snap-tests-global/migration-other-hook-tool/snap.txt @@ -37,6 +37,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -48,6 +50,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -59,6 +63,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -69,3 +75,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-oxlintrc-json-with-comments/snap.txt b/packages/cli/snap-tests-global/migration-oxlintrc-json-with-comments/snap.txt index 1cd39deb25..5af856074a 100644 --- a/packages/cli/snap-tests-global/migration-oxlintrc-json-with-comments/snap.txt +++ b/packages/cli/snap-tests-global/migration-oxlintrc-json-with-comments/snap.txt @@ -57,6 +57,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -68,6 +70,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -79,6 +83,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -89,3 +95,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-oxlintrc-jsonc/snap.txt b/packages/cli/snap-tests-global/migration-oxlintrc-jsonc/snap.txt index b33efba071..ea0bb36cce 100644 --- a/packages/cli/snap-tests-global/migration-oxlintrc-jsonc/snap.txt +++ b/packages/cli/snap-tests-global/migration-oxlintrc-jsonc/snap.txt @@ -59,6 +59,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -70,6 +72,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -81,6 +85,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -91,3 +97,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-partially-migrated-pre-commit/snap.txt b/packages/cli/snap-tests-global/migration-partially-migrated-pre-commit/snap.txt index f27bb9bbd1..10d47cf6d2 100644 --- a/packages/cli/snap-tests-global/migration-partially-migrated-pre-commit/snap.txt +++ b/packages/cli/snap-tests-global/migration-partially-migrated-pre-commit/snap.txt @@ -32,6 +32,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -43,6 +45,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -54,6 +58,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -64,6 +70,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat .husky/pre-commit # hook file should be unchanged (still has bootstrap) . "$(dirname -- "$0")/_/husky.sh" diff --git a/packages/cli/snap-tests-global/migration-prettier-eslint-combo/snap.txt b/packages/cli/snap-tests-global/migration-prettier-eslint-combo/snap.txt index 42f4a0a93c..13d0aa9d55 100644 --- a/packages/cli/snap-tests-global/migration-prettier-eslint-combo/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier-eslint-combo/snap.txt @@ -36,6 +36,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -47,6 +49,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -58,6 +62,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -68,6 +74,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > test ! -f eslint.config.mjs # check eslint config is removed > test ! -f .prettierrc.json # check prettier config is removed diff --git a/packages/cli/snap-tests-global/migration-prettier-ignore-unknown/snap.txt b/packages/cli/snap-tests-global/migration-prettier-ignore-unknown/snap.txt index 1a0a4b83ed..d126f6faa6 100644 --- a/packages/cli/snap-tests-global/migration-prettier-ignore-unknown/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier-ignore-unknown/snap.txt @@ -34,6 +34,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -45,6 +47,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -56,6 +60,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -66,5 +72,7 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > test ! -f .prettierrc.json # check prettier config is removed \ No newline at end of file diff --git a/packages/cli/snap-tests-global/migration-prettier-lint-staged/snap.txt b/packages/cli/snap-tests-global/migration-prettier-lint-staged/snap.txt index bd989fead2..2394bf1b2f 100644 --- a/packages/cli/snap-tests-global/migration-prettier-lint-staged/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier-lint-staged/snap.txt @@ -31,6 +31,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -42,6 +44,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -53,6 +57,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -63,6 +69,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat vite.config.ts # check oxfmt config and staged config merged into vite.config.ts import { defineConfig } from "vite-plus"; diff --git a/packages/cli/snap-tests-global/migration-prettier-pkg-json/snap.txt b/packages/cli/snap-tests-global/migration-prettier-pkg-json/snap.txt index 205af07ef1..08415367b8 100644 --- a/packages/cli/snap-tests-global/migration-prettier-pkg-json/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier-pkg-json/snap.txt @@ -32,6 +32,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -43,6 +45,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -54,6 +58,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -64,6 +70,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > cat vite.config.ts # check oxfmt config merged into vite.config.ts with semi/singleQuote settings import { defineConfig } from "vite-plus"; diff --git a/packages/cli/snap-tests-global/migration-prettier/snap.txt b/packages/cli/snap-tests-global/migration-prettier/snap.txt index f5f3ebe03e..92cc82ff73 100644 --- a/packages/cli/snap-tests-global/migration-prettier/snap.txt +++ b/packages/cli/snap-tests-global/migration-prettier/snap.txt @@ -34,6 +34,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -45,6 +47,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -56,6 +60,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -66,6 +72,8 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' > test ! -f .prettierrc.json # check prettier config is removed > cat vite.config.ts # check oxfmt config merged into vite.config.ts diff --git a/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt b/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt index f820188eb3..753912fd8d 100644 --- a/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt +++ b/packages/cli/snap-tests-global/migration-rewrite-declare-module/snap.txt @@ -57,6 +57,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -68,6 +70,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -79,6 +83,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -89,3 +95,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-rewrite-reference-types/snap.txt b/packages/cli/snap-tests-global/migration-rewrite-reference-types/snap.txt index ccc2680ecd..492f3e826f 100644 --- a/packages/cli/snap-tests-global/migration-rewrite-reference-types/snap.txt +++ b/packages/cli/snap-tests-global/migration-rewrite-reference-types/snap.txt @@ -6,7 +6,7 @@ > cat src/env.d.ts # check reference types rewritten /// /// -/// +/// /// /// /// diff --git a/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt b/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt index c947f9a67e..ecb7d5852e 100644 --- a/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt +++ b/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt @@ -1,11 +1,11 @@ > vp migrate --no-interactive # migration should skip rewriting vite imports when vite is in dependencies ◇ Migrated . to Vite+ • Node pnpm -• 2 config updates applied, 1 file had imports rewritten +• 2 config updates applied > cat src/index.ts # vite imports should NOT be rewritten, vitest imports SHOULD be rewritten import { defineConfig, type Plugin } from 'vite'; -import { describe, it, expect } from 'vite-plus/test'; +import { describe, it, expect } from 'vitest'; export function myApp(): Plugin { return { @@ -52,6 +52,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -63,6 +65,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -74,6 +78,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -84,3 +90,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt b/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt index 69d8ff381c..734cf42cfd 100644 --- a/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt +++ b/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt @@ -1,11 +1,11 @@ > vp migrate --no-interactive # migration should preserve vite peer contracts ◇ Migrated . to Vite+ • Node pnpm -• 2 config updates applied, 1 file had imports rewritten +• 2 config updates applied > cat src/index.ts # vite imports stay public, vitest imports rewrite import { defineConfig, type Plugin } from 'vite'; -import { describe, it, expect } from 'vite-plus/test'; +import { describe, it, expect } from 'vitest'; export function myVitePlugin(): Plugin { return { @@ -52,6 +52,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -63,6 +65,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -74,6 +78,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -84,3 +90,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-standalone-npm/snap.txt b/packages/cli/snap-tests-global/migration-standalone-npm/snap.txt index 49dc9a84b7..8f06e14f74 100644 --- a/packages/cli/snap-tests-global/migration-standalone-npm/snap.txt +++ b/packages/cli/snap-tests-global/migration-standalone-npm/snap.txt @@ -22,7 +22,9 @@ "@vitest/spy": "4.1.5", "@vitest/utils": "4.1.5", "@vitest/mocker": "4.1.5", - "@vitest/pretty-format": "4.1.5" + "@vitest/pretty-format": "4.1.5", + "@vitest/coverage-v8": "4.1.5", + "@vitest/coverage-istanbul": "4.1.5" } } diff --git a/packages/cli/snap-tests-global/migration-standalone-pnpm/snap.txt b/packages/cli/snap-tests-global/migration-standalone-pnpm/snap.txt index 2342efa842..a156c674eb 100644 --- a/packages/cli/snap-tests-global/migration-standalone-pnpm/snap.txt +++ b/packages/cli/snap-tests-global/migration-standalone-pnpm/snap.txt @@ -26,6 +26,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -37,6 +39,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -48,6 +52,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -58,3 +64,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-subpath/snap.txt b/packages/cli/snap-tests-global/migration-subpath/snap.txt index 9dca55906b..1eb44c77d5 100644 --- a/packages/cli/snap-tests-global/migration-subpath/snap.txt +++ b/packages/cli/snap-tests-global/migration-subpath/snap.txt @@ -46,6 +46,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -57,6 +59,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -68,6 +72,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -78,3 +84,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-tsconfig-esmoduleinterop/snap.txt b/packages/cli/snap-tests-global/migration-tsconfig-esmoduleinterop/snap.txt index 18426b11e0..d9e2991b1d 100644 --- a/packages/cli/snap-tests-global/migration-tsconfig-esmoduleinterop/snap.txt +++ b/packages/cli/snap-tests-global/migration-tsconfig-esmoduleinterop/snap.txt @@ -49,6 +49,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -60,6 +62,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -71,6 +75,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -81,3 +87,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-vite-version/snap.txt b/packages/cli/snap-tests-global/migration-vite-version/snap.txt index 8f6cc8e202..a3bb23f600 100644 --- a/packages/cli/snap-tests-global/migration-vite-version/snap.txt +++ b/packages/cli/snap-tests-global/migration-vite-version/snap.txt @@ -29,6 +29,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -40,6 +42,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -51,6 +55,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -61,3 +67,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/migration-vitest-peer-dep/snap.txt b/packages/cli/snap-tests-global/migration-vitest-peer-dep/snap.txt index 41ec83aefd..9c0939021e 100644 --- a/packages/cli/snap-tests-global/migration-vitest-peer-dep/snap.txt +++ b/packages/cli/snap-tests-global/migration-vitest-peer-dep/snap.txt @@ -32,6 +32,8 @@ catalog: '@vitest/utils': '@vitest/mocker': '@vitest/pretty-format': + '@vitest/coverage-v8': + '@vitest/coverage-istanbul': vite-plus: latest overrides: vite: 'catalog:' @@ -43,6 +45,8 @@ overrides: '@vitest/utils': 'catalog:' '@vitest/mocker': 'catalog:' '@vitest/pretty-format': 'catalog:' + '@vitest/coverage-v8': 'catalog:' + '@vitest/coverage-istanbul': 'catalog:' peerDependencyRules: allowAny: - vite @@ -54,6 +58,8 @@ peerDependencyRules: - '@vitest/utils' - '@vitest/mocker' - '@vitest/pretty-format' + - '@vitest/coverage-v8' + - '@vitest/coverage-istanbul' allowedVersions: vite: '*' vitest: '*' @@ -64,3 +70,5 @@ peerDependencyRules: '@vitest/utils': '*' '@vitest/mocker': '*' '@vitest/pretty-format': '*' + '@vitest/coverage-v8': '*' + '@vitest/coverage-istanbul': '*' diff --git a/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt b/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt index 73ea17a799..01a1f03a95 100644 --- a/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt +++ b/packages/cli/snap-tests-global/new-vite-monorepo-bun/snap.txt @@ -30,6 +30,8 @@ vite.config.ts "vite-plus": "catalog:" }, "overrides": { + "@vitest/coverage-istanbul": "catalog:", + "@vitest/coverage-v8": "catalog:", "@vitest/expect": "catalog:", "@vitest/mocker": "catalog:", "@vitest/pretty-format": "catalog:", @@ -54,6 +56,8 @@ vite.config.ts "@vitest/utils": "4.1.5", "@vitest/mocker": "4.1.5", "@vitest/pretty-format": "4.1.5", + "@vitest/coverage-v8": "4.1.5", + "@vitest/coverage-istanbul": "4.1.5", "vite-plus": "latest" } } diff --git a/packages/cli/snap-tests-global/new-vite-monorepo/snap.txt b/packages/cli/snap-tests-global/new-vite-monorepo/snap.txt index e3111bcf9c..737627ab7a 100644 --- a/packages/cli/snap-tests-global/new-vite-monorepo/snap.txt +++ b/packages/cli/snap-tests-global/new-vite-monorepo/snap.txt @@ -67,6 +67,8 @@ catalog: "@vitest/utils": "@vitest/mocker": "@vitest/pretty-format": + "@vitest/coverage-v8": + "@vitest/coverage-istanbul": vite-plus: latest overrides: vite: "catalog:" @@ -78,6 +80,8 @@ overrides: "@vitest/utils": "catalog:" "@vitest/mocker": "catalog:" "@vitest/pretty-format": "catalog:" + "@vitest/coverage-v8": "catalog:" + "@vitest/coverage-istanbul": "catalog:" peerDependencyRules: allowAny: - vite @@ -89,6 +93,8 @@ peerDependencyRules: - "@vitest/utils" - "@vitest/mocker" - "@vitest/pretty-format" + - "@vitest/coverage-v8" + - "@vitest/coverage-istanbul" allowedVersions: vite: "*" vitest: "*" @@ -99,6 +105,8 @@ peerDependencyRules: "@vitest/utils": "*" "@vitest/mocker": "*" "@vitest/pretty-format": "*" + "@vitest/coverage-v8": "*" + "@vitest/coverage-istanbul": "*" > test -f vite-plus-monorepo/.gitignore && echo '.gitignore exists' || echo 'ERROR: .gitignore missing' # verify gitignore renamed from _gitignore .gitignore exists diff --git a/packages/cli/snap-tests/create-org-bundled-monorepo/snap.txt b/packages/cli/snap-tests/create-org-bundled-monorepo/snap.txt index d7dffa4da5..46d377d1e3 100644 --- a/packages/cli/snap-tests/create-org-bundled-monorepo/snap.txt +++ b/packages/cli/snap-tests/create-org-bundled-monorepo/snap.txt @@ -34,6 +34,8 @@ catalog: "@vitest/utils": "@vitest/mocker": "@vitest/pretty-format": + "@vitest/coverage-v8": + "@vitest/coverage-istanbul": vite-plus: latest overrides: vite: "catalog:" @@ -45,6 +47,8 @@ overrides: "@vitest/utils": "catalog:" "@vitest/mocker": "catalog:" "@vitest/pretty-format": "catalog:" + "@vitest/coverage-v8": "catalog:" + "@vitest/coverage-istanbul": "catalog:" peerDependencyRules: allowAny: - vite @@ -56,6 +60,8 @@ peerDependencyRules: - "@vitest/utils" - "@vitest/mocker" - "@vitest/pretty-format" + - "@vitest/coverage-v8" + - "@vitest/coverage-istanbul" allowedVersions: vite: "*" vitest: "*" @@ -66,6 +72,8 @@ peerDependencyRules: "@vitest/utils": "*" "@vitest/mocker": "*" "@vitest/pretty-format": "*" + "@vitest/coverage-v8": "*" + "@vitest/coverage-istanbul": "*" > test -d my-mono/.git && echo 'Git initialized' # git-init prompt covers bundled monorepo path Git initialized From 4b82067fa8698ff2686eacabf9bc0c4d9a7c8046 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 14:52:15 +0800 Subject: [PATCH 23/37] style(migration): cargo fmt Trivial fmt-only fix on two test fixtures introduced by 21937c5b1. --- crates/vite_migration/src/import_rewriter.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/vite_migration/src/import_rewriter.rs b/crates/vite_migration/src/import_rewriter.rs index 71fa2caec2..44154be790 100644 --- a/crates/vite_migration/src/import_rewriter.rs +++ b/crates/vite_migration/src/import_rewriter.rs @@ -2518,8 +2518,7 @@ const x = 1; fn test_rewrite_reference_types_after_multiline_block_comment() { // Multi-line block comments should be skipped entirely. Use `vite-plus/test` // so the reverse-migration rule fires and we still observe a rewrite. - let content = - "/*\n * License header\n * Copyright 2024\n */\n/// \n"; + let content = "/*\n * License header\n * Copyright 2024\n */\n/// \n"; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); assert!(result.updated); assert_eq!( @@ -2619,8 +2618,7 @@ const x = 1; fn test_rewrite_reference_types_crlf() { // CRLF line endings should be preserved. Use a `vite-plus/test` reference // so the reverse-migration rule fires on the second line. - let content = - "/// \r\n/// \r\n"; + let content = "/// \r\n/// \r\n"; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); assert!(result.updated); assert_eq!( From 155a0a4326bbed376ec6cbe9c55e0651ae649c1d Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 15:07:49 +0800 Subject: [PATCH 24/37] revert(migration): restore `'vitest' -> 'vite-plus/test'` forward rewrite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 21937c5b1 swapped the Rust migrator's direction from `'vitest' -> 'vite-plus/test'` (forward) to `'vite-plus/test' -> 'vitest'` (reverse) to fix vinext's `vi.mock` hoister bug. But that broke `vp create` because template-generated test files use `from "vitest"` and the `test-vp-create.yml` CI workflow doesn't include the vitest family in its `VP_OVERRIDE_PACKAGES` env — so `vitest` is not installable in the generated project and `vp check` fails with TS2307. Restoring the forward rewrite means templates with `from "vitest"` become `from "vite-plus/test"` (which IS resolvable via the vite-plus dep). The `vi.mock` hoister bug for migrated projects returns, but that's already documented as an upstream blocker (PR comment 4466063059) — the cure was worse than the disease. Coverage-v8/coverage-istanbul overrides from 895e4dbc0 are kept. --- crates/vite_migration/src/import_rewriter.rs | 262 ++++++------------ .../migration-from-vitest-files/snap.txt | 2 +- .../snap.txt | 4 +- .../snap.txt | 2 +- .../migration-skip-vite-dependency/snap.txt | 4 +- .../snap.txt | 4 +- 6 files changed, 86 insertions(+), 192 deletions(-) diff --git a/crates/vite_migration/src/import_rewriter.rs b/crates/vite_migration/src/import_rewriter.rs index 44154be790..23d68b38bd 100644 --- a/crates/vite_migration/src/import_rewriter.rs +++ b/crates/vite_migration/src/import_rewriter.rs @@ -88,6 +88,7 @@ fix: $NEW_IMPORT /// ast-grep rules for rewriting vitest imports. /// /// This rewrites: +/// - `import { ... } from 'vitest'` → `import { ... } from 'vite-plus/test'` /// - `import { ... } from 'vitest/config'` → `import { ... } from 'vite-plus'` /// - `import { ... } from 'vitest/{name}'` → `import { ... } from 'vite-plus/test/{name}'` /// - `import { ... } from '@vitest/browser'` → `import { ... } from 'vite-plus/test/browser'` @@ -98,14 +99,6 @@ fix: $NEW_IMPORT /// - `import { ... } from '@vitest/browser-preview/{name}'` → `import { ... } from 'vite-plus/test/browser-preview/{name}'` /// - `import { ... } from '@vitest/browser-webdriverio'` → `import { ... } from 'vite-plus/test/browser-webdriverio'` /// - `import { ... } from '@vitest/browser-webdriverio/{name}'` → `import { ... } from 'vite-plus/test/browser-webdriverio/{name}'` -/// - `import { ... } from 'vite-plus/test'` → `import { ... } from 'vitest'` (reverse migration for the -/// bare-root specifier; required because `@vitest/mocker`'s static hoister hardcodes the -/// `vitest` specifier and runs before user plugins. Subpaths are intentionally preserved.) -/// -/// Note: the bare-root `'vitest'` specifier is intentionally NOT rewritten to `'vite-plus/test'` -/// any more. Migrated source must reach the upstream `vitest` module identity so that -/// `@vitest/mocker`'s hoister (which hardcodes `hoistedModule = "vitest"` and runs as part of -/// vitest's own plugin pipeline before user plugins) can intercept `vi.mock` calls. /// /// `declare module 'vitest' { ... }` (and the subpath/`@vitest/*` variants) are /// intentionally NOT rewritten — the `vite-plus/test*` subpaths are thin shims @@ -132,52 +125,52 @@ transform: by: "vite-plus" fix: $NEW_IMPORT --- -id: rewrite-vitest-scoped-import +id: rewrite-vitest-import language: TypeScript rule: pattern: $STR kind: string - regex: ^['"]@vitest/(browser-playwright|browser-preview|browser-webdriverio|browser)(/.*)?['"]$ + regex: ^['"]vitest['"]$ inside: kind: import_statement transform: NEW_IMPORT: replace: source: $STR - replace: "@vitest/" - by: "vite-plus/test/" + replace: vitest + by: "vite-plus/test" fix: $NEW_IMPORT --- -id: rewrite-vitest-subpath-import +id: rewrite-vitest-scoped-import language: TypeScript rule: pattern: $STR kind: string - regex: ^['"]vitest/.+['"]$ + regex: ^['"]@vitest/(browser-playwright|browser-preview|browser-webdriverio|browser)(/.*)?['"]$ inside: kind: import_statement transform: NEW_IMPORT: replace: source: $STR - replace: vitest/ + replace: "@vitest/" by: "vite-plus/test/" fix: $NEW_IMPORT --- -id: rewrite-vite-plus-test-to-vitest +id: rewrite-vitest-subpath-import language: TypeScript rule: pattern: $STR kind: string - regex: ^['"]vite-plus/test['"]$ + regex: ^['"]vitest/.+['"]$ inside: kind: import_statement transform: NEW_IMPORT: replace: source: $STR - replace: vite-plus/test - by: "vitest" + replace: vitest/ + by: "vite-plus/test/" fix: $NEW_IMPORT "#; @@ -272,18 +265,16 @@ static RE_REF_VITEST_CONFIG: LazyLock = LazyLock::new(|| { Regex::new(r#"^(\s*///\s*)"#).unwrap() }); +/// bare `vitest` → `vite-plus/test` +static RE_REF_VITEST: LazyLock = LazyLock::new(|| { + Regex::new(r#"^(\s*///\s*)"#).unwrap() +}); + /// `vitest/{subpath}` → `vite-plus/test/{subpath}` static RE_REF_VITEST_SUBPATH: LazyLock = LazyLock::new(|| { Regex::new(r#"^(\s*///\s*)"#).unwrap() }); -/// bare `vite-plus/test` → `vitest` (reverse migration for already-migrated sources). -/// Anchored so that only the exact root specifier matches — subpaths like -/// `vite-plus/test/browser` are intentionally preserved. -static RE_REF_VITE_PLUS_TEST: LazyLock = LazyLock::new(|| { - Regex::new(r#"^(\s*///\s*)"#).unwrap() -}); - /// `@vitest/{pkg}[/{subpath}]` → `vite-plus/test/{pkg}[/{subpath}]` /// Only matches packages and subpaths that vite-plus actually exports: /// - `@vitest/browser` → `vite-plus/test/browser` @@ -449,12 +440,6 @@ fn rewrite_reference_types(content: &mut String, skip_packages: &SkipPackages) - } // Each line matches at most one pattern; use early exit to skip remaining regexes. if !skip_packages.skip_vitest { - // Reverse migration: bare `vite-plus/test` → `vitest`. Anchored so that - // subpaths like `vite-plus/test/browser` are preserved. - if apply_regex_replace(line, &RE_REF_VITE_PLUS_TEST, "${1}vitest${2}") { - changed = true; - continue; - } if apply_regex_replace(line, &RE_REF_VITEST_CONFIG, "${1}vite-plus${2}") { changed = true; continue; @@ -467,8 +452,10 @@ fn rewrite_reference_types(content: &mut String, skip_packages: &SkipPackages) - changed = true; continue; } - // The bare `vitest` triple-slash reference is intentionally left alone — see - // the note on `REWRITE_VITEST_RULES` above. + if apply_regex_replace(line, &RE_REF_VITEST, "${1}vite-plus/test${2}") { + changed = true; + continue; + } } if !skip_packages.skip_vite { if apply_regex_replace(line, &RE_REF_VITE_SUBPATH, "${1}vite-plus/${2}${3}") { @@ -927,9 +914,6 @@ export default defineConfig({ #[test] fn test_rewrite_import_content_vitest() { - // Bare `vitest` is intentionally left untouched: vite-plus's runtime - // canonical specifier is `vitest`, and `@vitest/mocker`'s static hoister - // hardcodes that specifier and must see it unchanged. let vite_config = r#"import { describe, it, expect } from 'vitest'; describe('test', () => { @@ -939,20 +923,33 @@ describe('test', () => { });"#; let result = rewrite_import_content(vite_config, &SkipPackages::default()).unwrap(); - assert!(!result.updated); - assert_eq!(result.content, vite_config); + assert!(result.updated); + assert_eq!( + result.content, + r#"import { describe, it, expect } from 'vite-plus/test'; + +describe('test', () => { + it('should work', () => { + expect(true).toBe(true); + }); +});"# + ); } #[test] fn test_rewrite_import_content_vitest_double_quotes() { - // See note on `test_rewrite_import_content_vitest`: bare `vitest` is preserved. let vite_config = r#"import { describe, it, expect } from "vitest"; describe('test', () => {});"#; let result = rewrite_import_content(vite_config, &SkipPackages::default()).unwrap(); - assert!(!result.updated); - assert_eq!(result.content, vite_config); + assert!(result.updated); + assert_eq!( + result.content, + r#"import { describe, it, expect } from "vite-plus/test"; + +describe('test', () => {});"# + ); } #[test] @@ -1215,7 +1212,7 @@ export default defineConfig({ result.content, r#"import { defineConfig } from 'vite-plus'; import { ModuleRunner } from 'vite-plus/module-runner'; -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'vite-plus/test'; import { startVitest } from 'vite-plus/test/node'; import { page } from 'vite-plus/test/browser'; import { playwright } from 'vite-plus/test/browser-playwright'; @@ -1244,11 +1241,9 @@ export default defineConfig({});"#, ) .unwrap(); - // A previously-migrated source file with `vite-plus/test` — the migrator - // should reverse it back to `vitest`. fs::write( temp.path().join("src/test.ts"), - r#"import { describe, it } from 'vite-plus/test'; + r#"import { describe, it } from 'vitest'; describe('test', () => {});"#, ) .unwrap(); @@ -1288,8 +1283,7 @@ describe('test', () => {});"#, assert!(config_content.contains("vite-plus")); let test_content = fs::read_to_string(temp.path().join("src/test.ts")).unwrap(); - assert!(test_content.contains("from 'vitest'")); - assert!(!test_content.contains("vite-plus/test")); + assert!(test_content.contains("vite-plus/test")); // Verify utils.ts was not modified let utils_content = fs::read_to_string(temp.path().join("src/utils.ts")).unwrap(); @@ -1573,7 +1567,7 @@ export default defineConfig({});"#; assert_eq!( result.content, r#"import { defineConfig } from 'vite-plus'; -import { describe } from 'vitest'; +import { describe } from 'vite-plus/test'; declare module 'vite-plus' { interface UserConfig { @@ -1906,12 +1900,9 @@ export default defineConfig({ #[test] fn test_skip_vite_when_peer_dependency() { - // When vite is a peerDependency, vite imports should NOT be rewritten. - // The vitest import is the canonical specifier and is also preserved as-is — - // exercise the reverse-migration path by including a `vite-plus/test` import. + // When vite is a peerDependency, vite imports should NOT be rewritten let content = r#"import { defineConfig } from 'vite'; import { describe } from 'vitest'; -import { vi } from 'vite-plus/test'; export default defineConfig({});"#; @@ -1920,13 +1911,11 @@ export default defineConfig({});"#; let result = rewrite_import_content(content, &skip_packages).unwrap(); assert!(result.updated); - // vite import should NOT be rewritten; vitest import already canonical; - // vite-plus/test should be reverse-migrated to vitest. + // vite import should NOT be rewritten, vitest import SHOULD be rewritten assert_eq!( result.content, r#"import { defineConfig } from 'vite'; -import { describe } from 'vitest'; -import { vi } from 'vitest'; +import { describe } from 'vite-plus/test'; export default defineConfig({});"# ); @@ -2125,10 +2114,9 @@ export default defineConfig({});"#; // Create src directory fs::create_dir(temp.path().join("src")).unwrap(); - // Create source file with vite import (preserved because vite is a dep) - // and a previously-migrated `vite-plus/test` import (must be reverse-migrated). + // Create source file with vite and vitest imports let original_content = r#"import { defineConfig } from 'vite'; -import { vi } from 'vite-plus/test'; +import { describe } from 'vitest'; export default defineConfig({});"#; fs::write(temp.path().join("src/index.ts"), original_content).unwrap(); @@ -2136,16 +2124,16 @@ export default defineConfig({});"#; // Run the batch rewrite let result = rewrite_imports_in_directory(temp.path()).unwrap(); - // File should be modified (vite-plus/test was reverse-migrated) + // File should be modified (vitest was rewritten) assert_eq!(result.modified_files.len(), 1); assert!(result.errors.is_empty()); - // Verify vite import NOT rewritten (in dependencies), vite-plus/test IS reverse-rewritten + // Verify vite import NOT rewritten (in dependencies), vitest IS rewritten let content = fs::read_to_string(temp.path().join("src/index.ts")).unwrap(); assert_eq!( content, r#"import { defineConfig } from 'vite'; -import { vi } from 'vitest'; +import { describe } from 'vite-plus/test'; export default defineConfig({});"# ); @@ -2169,10 +2157,9 @@ export default defineConfig({});"# // Create src directory fs::create_dir(temp.path().join("src")).unwrap(); - // Create source file with vite import (preserved because vite is peerDep) - // and a previously-migrated `vite-plus/test` import (must be reverse-migrated). + // Create source file with vite and vitest imports let original_content = r#"import { defineConfig } from 'vite'; -import { vi } from 'vite-plus/test'; +import { describe } from 'vitest'; export default defineConfig({});"#; fs::write(temp.path().join("src/index.ts"), original_content).unwrap(); @@ -2180,16 +2167,16 @@ export default defineConfig({});"#; // Run the batch rewrite let result = rewrite_imports_in_directory(temp.path()).unwrap(); - // File should be modified (vite-plus/test was reverse-migrated) + // File should be modified (vitest was rewritten) assert_eq!(result.modified_files.len(), 1); assert!(result.errors.is_empty()); - // Verify vite import NOT rewritten, vite-plus/test IS reverse-rewritten + // Verify vite import NOT rewritten, vitest IS rewritten let content = fs::read_to_string(temp.path().join("src/index.ts")).unwrap(); assert_eq!( content, r#"import { defineConfig } from 'vite'; -import { vi } from 'vitest'; +import { describe } from 'vite-plus/test'; export default defineConfig({});"# ); @@ -2292,22 +2279,20 @@ import { build } from 'tsdown';"#; // app package.json (no peerDeps) fs::write(temp.path().join("packages/app/package.json"), r#"{"name": "app"}"#).unwrap(); - // vite-plugin source file: vite import preserved (peerDep) and a - // previously-migrated `vite-plus/test` import that needs reverse-migration. + // vite-plugin source file with vite and vitest imports fs::write( temp.path().join("packages/vite-plugin/src/index.ts"), r#"import { defineConfig } from 'vite'; -import { vi } from 'vite-plus/test'; +import { describe } from 'vitest'; export default defineConfig({});"#, ) .unwrap(); - // app source file: vite import (will be rewritten) and a previously-migrated - // `vite-plus/test` import (must be reverse-migrated). + // app source file with vite and vitest imports fs::write( temp.path().join("packages/app/src/index.ts"), r#"import { defineConfig } from 'vite'; -import { vi } from 'vite-plus/test'; +import { describe } from 'vitest'; export default defineConfig({});"#, ) .unwrap(); @@ -2318,23 +2303,23 @@ export default defineConfig({});"#, // Both files should be modified assert_eq!(result.modified_files.len(), 2); - // vite-plugin: vite NOT rewritten (has peerDep), vite-plus/test reverse-migrated + // vite-plugin: vite NOT rewritten (has peerDep), vitest IS rewritten let vite_plugin_content = fs::read_to_string(temp.path().join("packages/vite-plugin/src/index.ts")).unwrap(); assert_eq!( vite_plugin_content, r#"import { defineConfig } from 'vite'; -import { vi } from 'vitest'; +import { describe } from 'vite-plus/test'; export default defineConfig({});"# ); - // app: vite IS rewritten (no peerDep), vite-plus/test reverse-migrated + // app: vite IS rewritten (no peerDep), vitest IS rewritten let app_content = fs::read_to_string(temp.path().join("packages/app/src/index.ts")).unwrap(); assert_eq!( app_content, r#"import { defineConfig } from 'vite-plus'; -import { vi } from 'vitest'; +import { describe } from 'vite-plus/test'; export default defineConfig({});"# ); } @@ -2369,12 +2354,10 @@ export default defineConfig({});"# #[test] fn test_rewrite_reference_types_bare_vitest() { - // Bare `vitest` triple-slash reference is intentionally preserved: see - // the `REWRITE_VITEST_RULES` note. The canonical specifier is `vitest`. let content = r#"/// "#; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(!result.updated); - assert_eq!(result.content, content); + assert!(result.updated); + assert_eq!(result.content, r#"/// "#); } #[test] @@ -2516,14 +2499,14 @@ const x = 1; #[test] fn test_rewrite_reference_types_after_multiline_block_comment() { - // Multi-line block comments should be skipped entirely. Use `vite-plus/test` - // so the reverse-migration rule fires and we still observe a rewrite. - let content = "/*\n * License header\n * Copyright 2024\n */\n/// \n"; + // Multi-line block comments should be skipped entirely + let content = + "/*\n * License header\n * Copyright 2024\n */\n/// \n"; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); assert!(result.updated); assert_eq!( result.content, - "/*\n * License header\n * Copyright 2024\n */\n/// \n" + "/*\n * License header\n * Copyright 2024\n */\n/// \n" ); } @@ -2616,14 +2599,14 @@ const x = 1; #[test] fn test_rewrite_reference_types_crlf() { - // CRLF line endings should be preserved. Use a `vite-plus/test` reference - // so the reverse-migration rule fires on the second line. - let content = "/// \r\n/// \r\n"; + // CRLF line endings should be preserved + let content = + "/// \r\n/// \r\n"; let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); assert!(result.updated); assert_eq!( result.content, - "/// \r\n/// \r\n" + "/// \r\n/// \r\n" ); } @@ -2715,10 +2698,8 @@ const x = 1; #[test] fn test_rewrite_reference_types_env_d_ts_style() { - // Bare `vitest` is intentionally preserved (canonical specifier). - // Use `vite-plus/test` instead to exercise the reverse-migration rule. let content = r#"/// -/// +/// /// /// /// "#; @@ -2728,7 +2709,7 @@ const x = 1; assert_eq!( result.content, r#"/// -/// +/// /// /// /// "# @@ -2755,11 +2736,8 @@ export default defineConfig({});"# #[test] fn test_rewrite_reference_types_skip_vite() { - // With vite skipped, only the vitest reference is processed. Use `vite-plus/test` - // (the deprecated specifier) so the reverse-migration rule fires; bare `vitest` - // is preserved as the canonical specifier. let content = r#"/// -/// "#; +/// "#; let skip_packages = SkipPackages { skip_vite: true, skip_vitest: false, skip_tsdown: false }; @@ -2768,7 +2746,7 @@ export default defineConfig({});"# assert_eq!( result.content, r#"/// -/// "# +/// "# ); } @@ -2817,88 +2795,4 @@ export default defineConfig({});"# assert!(!result.updated); assert_eq!(result.content, content); } - - #[test] - fn test_rewrite_import_content_vite_plus_test_to_vitest() { - // Reverse migration: a previously-migrated source that still has - // `from 'vite-plus/test'` must be rewritten back to `from 'vitest'`, - // because `@vitest/mocker`'s static hoister hardcodes the `vitest` - // specifier and runs before user plugins. - let source = r#"import { vi, describe, it } from 'vite-plus/test'; - -describe('mock', () => { - vi.mock('./dep'); -});"#; - - let result = rewrite_import_content(source, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"import { vi, describe, it } from 'vitest'; - -describe('mock', () => { - vi.mock('./dep'); -});"# - ); - } - - #[test] - fn test_rewrite_import_content_vite_plus_test_double_quotes_to_vitest() { - let source = r#"import { vi } from "vite-plus/test"; - -vi.mock("./dep");"#; - - let result = rewrite_import_content(source, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!( - result.content, - r#"import { vi } from "vitest"; - -vi.mock("./dep");"# - ); - } - - #[test] - fn test_rewrite_import_content_vite_plus_test_subpath_preserved() { - // Subpaths under `vite-plus/test` are vite-plus exports (shims for the - // browser provider packages) and MUST NOT be reverse-rewritten. - let source = r#"import { playwright } from 'vite-plus/test/browser-playwright'; -import { page } from 'vite-plus/test/browser'; - -export { playwright, page };"#; - - let result = rewrite_import_content(source, &SkipPackages::default()).unwrap(); - assert!(!result.updated); - assert_eq!(result.content, source); - } - - #[test] - fn test_rewrite_reference_types_vite_plus_test_to_vitest() { - // Reverse-direction triple-slash reference rewrite: bare root only. - let content = r#"/// "#; - let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(result.updated); - assert_eq!(result.content, r#"/// "#); - } - - #[test] - fn test_rewrite_reference_types_vite_plus_test_subpath_preserved() { - // Subpaths under `vite-plus/test` map to dedicated vite-plus exports - // and must not be rewritten back to `@vitest/*`. - let content = r#"/// "#; - let result = rewrite_import_content(content, &SkipPackages::default()).unwrap(); - assert!(!result.updated); - assert_eq!(result.content, content); - } - - #[test] - fn test_rewrite_import_content_vite_plus_test_skipped_when_vitest_skipped() { - // When the package declares `vitest` as a dep/peerDep, no vitest-family - // rewrites should fire — including the reverse one. - let source = r#"import { vi } from 'vite-plus/test';"#; - let skip = SkipPackages { skip_vite: false, skip_vitest: true, skip_tsdown: false }; - let result = rewrite_import_content(source, &skip).unwrap(); - assert!(!result.updated); - assert_eq!(result.content, source); - } } diff --git a/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt b/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt index 345c9bbdf5..2715368e19 100644 --- a/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt +++ b/packages/cli/snap-tests-global/migration-from-vitest-files/snap.txt @@ -77,7 +77,7 @@ peerDependencyRules: > cat test/hello.ts # check test/hello.ts import { server } from 'vite-plus/test/browser-playwright/context'; -import { test, describe, expect, it } from 'vitest'; +import { test, describe, expect, it } from 'vite-plus/test'; const { readFile } = server.commands; diff --git a/packages/cli/snap-tests-global/migration-monorepo-skip-vite-peer-dependency/snap.txt b/packages/cli/snap-tests-global/migration-monorepo-skip-vite-peer-dependency/snap.txt index 5ed3e43cc0..dfe73cacba 100644 --- a/packages/cli/snap-tests-global/migration-monorepo-skip-vite-peer-dependency/snap.txt +++ b/packages/cli/snap-tests-global/migration-monorepo-skip-vite-peer-dependency/snap.txt @@ -1,11 +1,11 @@ > vp migrate --no-interactive # migration should preserve vite peer contracts in workspace packages ◇ Migrated . to Vite+ • Node pnpm -• 2 config updates applied +• 2 config updates applied, 1 file had imports rewritten > cat packages/vite-plugin/src/index.ts # vite-plugin has vite in peerDeps: vite imports stay public, vitest rewrites import { defineConfig, type Plugin } from 'vite'; -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'vite-plus/test'; export function myVitePlugin(): Plugin { return { diff --git a/packages/cli/snap-tests-global/migration-rewrite-reference-types/snap.txt b/packages/cli/snap-tests-global/migration-rewrite-reference-types/snap.txt index 492f3e826f..ccc2680ecd 100644 --- a/packages/cli/snap-tests-global/migration-rewrite-reference-types/snap.txt +++ b/packages/cli/snap-tests-global/migration-rewrite-reference-types/snap.txt @@ -6,7 +6,7 @@ > cat src/env.d.ts # check reference types rewritten /// /// -/// +/// /// /// /// diff --git a/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt b/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt index ecb7d5852e..55d3c2fe1f 100644 --- a/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt +++ b/packages/cli/snap-tests-global/migration-skip-vite-dependency/snap.txt @@ -1,11 +1,11 @@ > vp migrate --no-interactive # migration should skip rewriting vite imports when vite is in dependencies ◇ Migrated . to Vite+ • Node pnpm -• 2 config updates applied +• 2 config updates applied, 1 file had imports rewritten > cat src/index.ts # vite imports should NOT be rewritten, vitest imports SHOULD be rewritten import { defineConfig, type Plugin } from 'vite'; -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'vite-plus/test'; export function myApp(): Plugin { return { diff --git a/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt b/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt index 734cf42cfd..ebca02e4f6 100644 --- a/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt +++ b/packages/cli/snap-tests-global/migration-skip-vite-peer-dependency/snap.txt @@ -1,11 +1,11 @@ > vp migrate --no-interactive # migration should preserve vite peer contracts ◇ Migrated . to Vite+ • Node pnpm -• 2 config updates applied +• 2 config updates applied, 1 file had imports rewritten > cat src/index.ts # vite imports stay public, vitest imports rewrite import { defineConfig, type Plugin } from 'vite'; -import { describe, it, expect } from 'vitest'; +import { describe, it, expect } from 'vite-plus/test'; export function myVitePlugin(): Plugin { return { From dd76ace414e995f798f1f90b83d8806d50ef195b Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 15:17:02 +0800 Subject: [PATCH 25/37] chore: retrigger CI after empty period From 460d112f3f92d0ea46adb84e61b2623eee09949c Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 15:40:07 +0800 Subject: [PATCH 26/37] fix(cli): re-export vitest/config types (ViteUserConfig, etc.) Task #56 narrowed `export * from 'vitest/config'` to an explicit list, but missed the vitest-specific type aliases (ViteUserConfig, ViteUserConfigExport, TestProjectConfiguration, TestUserConfig, etc.). Downstream like vue-mini imports `ViteUserConfig` from 'vite-plus' and broke with TS2724. Add the full set of vitest-only type exports. Runtime exports (mergeConfig, defineConfig, loadConfigFromFile) still come from vite-plus-core only to avoid star-export conflicts. --- packages/cli/src/index.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index cf796c9d9d..ae6440f7c9 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -11,4 +11,20 @@ export { defineProject, } from 'vitest/config'; +export type { + TestProjectConfiguration, + TestProjectInlineConfiguration, + TestTagDefinition, + TestUserConfig, + UserProjectConfigExport, + UserProjectConfigFn, + UserWorkspaceConfig, + ViteUserConfig, + ViteUserConfigExport, + ViteUserConfigFn, + ViteUserConfigFnObject, + ViteUserConfigFnPromise, + WatcherTriggerPattern, +} from 'vitest/config'; + export { defineConfig, lazyPlugins }; From 261787ed6300b14c1b1796b2e66e57ec31557d8d Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 16:00:11 +0800 Subject: [PATCH 27/37] test(snap): drop leading whitespace on pnpm10 Packages line pnpm v10 changed the formatting of the `Packages: +` summary line (no longer indented). Update the captured snaps for `command-list-pnpm10-with-workspace` and `command-outdated-pnpm10` to match. Verified locally that subsequent runs produce no diff. --- .../command-list-pnpm10-with-workspace/snap.txt | 2 +- packages/cli/snap-tests-global/command-outdated-pnpm10/snap.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/snap-tests-global/command-list-pnpm10-with-workspace/snap.txt b/packages/cli/snap-tests-global/command-list-pnpm10-with-workspace/snap.txt index 54ebf902c2..8b3872dce4 100644 --- a/packages/cli/snap-tests-global/command-list-pnpm10-with-workspace/snap.txt +++ b/packages/cli/snap-tests-global/command-list-pnpm10-with-workspace/snap.txt @@ -1,6 +1,6 @@ > vp install # should install packages first Scope: all workspace projects -  Packages: + +Packages: + + Progress: resolved , reused , downloaded , added , done diff --git a/packages/cli/snap-tests-global/command-outdated-pnpm10/snap.txt b/packages/cli/snap-tests-global/command-outdated-pnpm10/snap.txt index 532cd5ed1e..ec085ee577 100644 --- a/packages/cli/snap-tests-global/command-outdated-pnpm10/snap.txt +++ b/packages/cli/snap-tests-global/command-outdated-pnpm10/snap.txt @@ -145,7 +145,7 @@ testnpm2 └──────────────────────────────────┴─────────┴────────┘ [1]> vp outdated --no-optional # should support no-optional output -  ┌──────────────────────────────────┬─────────┬────────┐ +┌──────────────────────────────────┬─────────┬────────┐ │ Package │ Current │ Latest │ ├──────────────────────────────────┼─────────┼────────┤ │ testnpm2 │ │ From 91ba5cf301860a8dc00200b1cb08379f63077628 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 16:14:39 +0800 Subject: [PATCH 28/37] fix(cli): propagate vite-plus/test rewrite plugin into test.projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The mocker rewrite plugin was only injected into the root vite config, so projects defined under `test.projects` (each spinning up an isolated Vite pipeline) never got the rewrite — `vi.mock()` failed with "problems in resolving the mocks API" for source that imports from `'vite-plus/test'` inside a project. --- .../define-config-mocker-rewrite.spec.ts | 91 ++++++++++++++++++- packages/cli/src/define-config.ts | 70 +++++++++++++- 2 files changed, 158 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts b/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts index be0757c239..8b281b9316 100644 --- a/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts +++ b/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts @@ -1,6 +1,16 @@ +import type { Plugin } from '@voidzero-dev/vite-plus-core'; import { describe, expect, it } from 'vitest'; -import { rewriteVitePlusTestSpecifier } from '../define-config.ts'; +import { defineConfig, rewriteVitePlusTestSpecifier } from '../define-config.ts'; + +const REWRITE_PLUGIN_NAME = 'vite-plus:vitest-specifier-rewrite'; + +function pluginName(p: unknown): string | undefined { + if (p && typeof p === 'object' && 'name' in p && typeof (p as { name: unknown }).name === 'string') { + return (p as { name: string }).name; + } + return undefined; +} describe('rewriteVitePlusTestSpecifier', () => { it('is a no-op when source does not mention vite-plus/test', () => { @@ -66,3 +76,82 @@ describe('rewriteVitePlusTestSpecifier', () => { expect(rewriteVitePlusTestSpecifier(input)).toBe(expected); }); }); + +describe('defineConfig project plugin injection', () => { + it('injects rewrite plugin at the root plugins array', () => { + const existing: Plugin = { name: 'user-existing-root-plugin' }; + const result = defineConfig({ plugins: [existing] }) as { plugins: unknown[] }; + + expect(pluginName(result.plugins[0])).toBe(REWRITE_PLUGIN_NAME); + expect(pluginName(result.plugins[1])).toBe('user-existing-root-plugin'); + }); + + it('injects rewrite plugin into an inline-object project entry, preserving existing plugins', () => { + const existing: Plugin = { name: 'user-unit-project-plugin' }; + const result = defineConfig({ + test: { + projects: [ + { + plugins: [existing], + test: { name: 'unit', include: ['test/unit/**/*.spec.ts'], environment: 'node' }, + }, + ], + }, + }) as { test: { projects: unknown[] } }; + + const project = result.test.projects[0] as { plugins: unknown[]; test: { name: string } }; + expect(project.test.name).toBe('unit'); + expect(pluginName(project.plugins[0])).toBe(REWRITE_PLUGIN_NAME); + expect(pluginName(project.plugins[1])).toBe('user-unit-project-plugin'); + // Sanity: the existing plugin reference is preserved (clone shallow-copies the array). + expect(project.plugins[1]).toBe(existing); + }); + + it('injects rewrite plugin into the return value of a function-shaped project entry', () => { + const existing: Plugin = { name: 'user-fn-project-plugin' }; + const projectFn = () => ({ + plugins: [existing], + test: { name: 'nuxt', environment: 'happy-dom' as const }, + }); + const result = defineConfig({ + test: { projects: [projectFn] }, + }) as { test: { projects: unknown[] } }; + + const wrapped = result.test.projects[0]; + expect(typeof wrapped).toBe('function'); + + // Vitest passes a `ConfigEnv` to the function; we don't depend on its + // shape here, the wrapper just forwards it. + const fakeEnv = { mode: 'test', command: 'serve' as const }; + const resolved = (wrapped as (env: typeof fakeEnv) => { plugins: unknown[] })(fakeEnv); + expect(pluginName(resolved.plugins[0])).toBe(REWRITE_PLUGIN_NAME); + expect(pluginName(resolved.plugins[1])).toBe('user-fn-project-plugin'); + }); + + it('passes string-glob project entries through unchanged', () => { + const result = defineConfig({ + test: { + projects: ['./packages/*', './apps/*'], + }, + }) as { test: { projects: unknown[] } }; + + expect(result.test.projects).toEqual(['./packages/*', './apps/*']); + }); + + it('handles projects with no existing plugins array', () => { + const result = defineConfig({ + test: { + projects: [ + { + test: { name: 'no-plugins', environment: 'node' }, + }, + ], + }, + }) as { test: { projects: unknown[] } }; + + const project = result.test.projects[0] as { plugins: unknown[]; test: { name: string } }; + expect(project.test.name).toBe('no-plugins'); + expect(project.plugins).toHaveLength(1); + expect(pluginName(project.plugins[0])).toBe(REWRITE_PLUGIN_NAME); + }); +}); diff --git a/packages/cli/src/define-config.ts b/packages/cli/src/define-config.ts index 6f3322f5b0..904b9eecd5 100644 --- a/packages/cli/src/define-config.ts +++ b/packages/cli/src/define-config.ts @@ -1,7 +1,13 @@ import type { PluginOption, UserConfig } from '@voidzero-dev/vite-plus-core'; import type { OxfmtConfig } from 'oxfmt'; import type { OxlintConfig } from 'oxlint'; -import { defineConfig as viteDefineConfig, type ConfigEnv } from 'vitest/config'; +import { + defineConfig as viteDefineConfig, + type ConfigEnv, + type TestProjectConfiguration, + type TestProjectInlineConfiguration, + type UserProjectConfigFn, +} from 'vitest/config'; import type { InlineConfig as VitestInlineConfig } from 'vitest/node'; import type { PackUserConfig } from './pack.ts'; @@ -98,13 +104,73 @@ function vitePlusTestSpecifierRewritePlugin(): PluginOption { }; } -function injectPlugin(config: UserConfig): UserConfig { +/** + * Inject the rewrite plugin into a single inline project config. Used both + * for root configs and for object-shaped entries inside `test.projects`. + * + * The shapes overlap (both have an optional top-level `plugins` array), so a + * shared helper keeps the wiring consistent. + */ +function injectPluginIntoInlineConfig( + config: T, +): T { return { ...config, plugins: [vitePlusTestSpecifierRewritePlugin(), ...(config.plugins ?? [])], }; } +/** + * Walk `config.test?.projects` and inject the rewrite plugin into each + * project entry. Vitest spins up an independent Vite pipeline per project, so + * root-level plugins do NOT propagate — without this, files matched by a + * project's `include` glob never get the `vite-plus/test` → `vitest` rewrite. + * + * Entry shapes (from `TestProjectConfiguration`): + * - string (glob path like `'./packages/*'`) → passed through unchanged. + * - object (inline config with `test: {...}`) → clone and prepend plugin. + * - function (sync or async) → wrap so its result is injected. + * - Promise (resolves to inline config) → chain `.then(injectPlugin)`. + */ +function injectPluginIntoProject(project: TestProjectConfiguration): TestProjectConfiguration { + if (typeof project === 'string') { + return project; + } + if (typeof project === 'function') { + const fn = project as UserProjectConfigFn; + const wrapped: UserProjectConfigFn = (env: ConfigEnv) => { + const result = fn(env); + if (result instanceof Promise) { + return result.then(injectPluginIntoInlineConfig); + } + return injectPluginIntoInlineConfig(result); + }; + return wrapped; + } + if (project instanceof Promise) { + return project.then(injectPluginIntoInlineConfig); + } + if (typeof project === 'object' && project !== null) { + return injectPluginIntoInlineConfig(project as TestProjectInlineConfiguration); + } + return project; +} + +function injectPlugin(config: UserConfig): UserConfig { + const injected = injectPluginIntoInlineConfig(config); + const projects = injected.test?.projects; + if (!projects || projects.length === 0) { + return injected; + } + return { + ...injected, + test: { + ...injected.test, + projects: projects.map(injectPluginIntoProject), + }, + }; +} + function injectPluginIntoConfig(config: ViteUserConfigExport): ViteUserConfigExport { if (typeof config === 'function') { return (env: ConfigEnv) => { From 2610920b5ab6abfead0b75c7457731522116bd1e Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 16:23:22 +0800 Subject: [PATCH 29/37] chore: apply oxfmt formatting Fix `vp check` formatting failures from a13027fd6. --- .../cli/src/__tests__/define-config-mocker-rewrite.spec.ts | 7 ++++++- packages/cli/src/define-config.ts | 4 +--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts b/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts index 8b281b9316..1e6782e12a 100644 --- a/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts +++ b/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts @@ -6,7 +6,12 @@ import { defineConfig, rewriteVitePlusTestSpecifier } from '../define-config.ts' const REWRITE_PLUGIN_NAME = 'vite-plus:vitest-specifier-rewrite'; function pluginName(p: unknown): string | undefined { - if (p && typeof p === 'object' && 'name' in p && typeof (p as { name: unknown }).name === 'string') { + if ( + p && + typeof p === 'object' && + 'name' in p && + typeof (p as { name: unknown }).name === 'string' + ) { return (p as { name: string }).name; } return undefined; diff --git a/packages/cli/src/define-config.ts b/packages/cli/src/define-config.ts index 904b9eecd5..06de596952 100644 --- a/packages/cli/src/define-config.ts +++ b/packages/cli/src/define-config.ts @@ -111,9 +111,7 @@ function vitePlusTestSpecifierRewritePlugin(): PluginOption { * The shapes overlap (both have an optional top-level `plugins` array), so a * shared helper keeps the wiring consistent. */ -function injectPluginIntoInlineConfig( - config: T, -): T { +function injectPluginIntoInlineConfig(config: T): T { return { ...config, plugins: [vitePlusTestSpecifierRewritePlugin(), ...(config.plugins ?? [])], From a0d248e65ed556b31b5bd72b5fb78362d745f6a1 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 16:41:21 +0800 Subject: [PATCH 30/37] fix(cli): drop redundant type assertions in project injector TS infers the narrowed types after `typeof project === 'function'` and `typeof project === 'object' && project !== null`, so the explicit casts trip `typescript(no-unnecessary-type-assertion)`. --- packages/cli/src/define-config.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/define-config.ts b/packages/cli/src/define-config.ts index 06de596952..fe3f49c707 100644 --- a/packages/cli/src/define-config.ts +++ b/packages/cli/src/define-config.ts @@ -5,7 +5,6 @@ import { defineConfig as viteDefineConfig, type ConfigEnv, type TestProjectConfiguration, - type TestProjectInlineConfiguration, type UserProjectConfigFn, } from 'vitest/config'; import type { InlineConfig as VitestInlineConfig } from 'vitest/node'; @@ -135,9 +134,8 @@ function injectPluginIntoProject(project: TestProjectConfiguration): TestProject return project; } if (typeof project === 'function') { - const fn = project as UserProjectConfigFn; const wrapped: UserProjectConfigFn = (env: ConfigEnv) => { - const result = fn(env); + const result = project(env); if (result instanceof Promise) { return result.then(injectPluginIntoInlineConfig); } @@ -149,7 +147,7 @@ function injectPluginIntoProject(project: TestProjectConfiguration): TestProject return project.then(injectPluginIntoInlineConfig); } if (typeof project === 'object' && project !== null) { - return injectPluginIntoInlineConfig(project as TestProjectInlineConfiguration); + return injectPluginIntoInlineConfig(project); } return project; } From cccf7c97345d2a469f1730e7a00f1087a66d3e49 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 17:48:41 +0800 Subject: [PATCH 31/37] fix(cli): add runtime targets for browser provider context exports `vp migrate` rewrites `@vitest/browser/context` and `@vitest/browser-{playwright,preview,webdriverio}/context` to the corresponding `vite-plus/test/...` subpaths, but those entries only declared a `types` path. Node's resolver returned `ERR_PACKAGE_PATH_NOT_EXPORTED` at runtime on migrated browser-mode projects. `syncTestPackageExports` now emits a runtime shim that re-exports from upstream `@vitest/browser/context` (which itself is a stub that Vitest replaces in browser mode) and adds `default` keys to all six context entries. --- packages/cli/build.ts | 69 +++++++++++++++++++++++++++++++++++++++ packages/cli/package.json | 22 +++++++++---- 2 files changed, 85 insertions(+), 6 deletions(-) diff --git a/packages/cli/build.ts b/packages/cli/build.ts index 617fb1643d..dd40685aea 100644 --- a/packages/cli/build.ts +++ b/packages/cli/build.ts @@ -411,6 +411,15 @@ async function syncTestPackageExports() { { providerPkgRoot }, ); if (shimExport) { + // Upstream `@vitest/browser-/context` is types-only and just + // re-exports from `@vitest/browser/context`. To make the migrated + // `vite-plus/test/browser-/context` import resolvable at + // runtime (Node ESM resolution requires `default`/`import`), emit a + // JS shim that re-exports from `@vitest/browser/context` and amend + // the export entry. + if (providerExportPath === './context') { + await ensureContextRuntimeShim(shimBaseName, testDistDir, shimExport); + } generatedExports[cliPath] = shimExport; console.log(` Created ${cliPath}`); } @@ -418,6 +427,13 @@ async function syncTestPackageExports() { } } + // Emit `./test/browser/context` — vitest's exports map only covers `./browser` + // (which becomes `vite-plus/test/browser`), but the migration rewrites + // `@vitest/browser/context` → `vite-plus/test/browser/context`. Without this + // entry Node throws ERR_PACKAGE_PATH_NOT_EXPORTED at runtime. + generatedExports['./test/browser/context'] = await createBrowserContextExport(testDistDir); + console.log(' Created ./test/browser/context'); + // Update CLI package.json await updateCliPackageJson(cliPkgPath, generatedExports); @@ -587,6 +603,59 @@ async function writePrivateAtVitestBrowserShims(testDistDir: string): Promise/context` is declared types-only (its + * `context.d.ts` simply re-exports from `@vitest/browser/context`). After the + * migration rewrites `@vitest/browser-/context` → + * `vite-plus/test/browser-/context`, Node ESM resolution fails with + * ERR_PACKAGE_PATH_NOT_EXPORTED unless the export entry has a `default`/`import` + * target. We re-export from `@vitest/browser/context` so the bundled + * `@vitest/browser` (vite-plus's own pnpm-edge) is reached at runtime. + */ +async function ensureContextRuntimeShim( + shimBaseName: string, + testDistDir: string, + shimExport: ExportValue, +): Promise { + if (typeof shimExport !== 'object' || shimExport === null) { + return; + } + const entry = shimExport as Record; + if (entry.default || entry.import) { + return; + } + const jsRelPath = `./dist/test/${shimBaseName}.js`; + const jsAbsPath = join(testDistDir, `${shimBaseName}.js`); + await mkdir(dirname(jsAbsPath), { recursive: true }); + await writeFile(jsAbsPath, `export * from '@vitest/browser/context';\n`); + entry.default = jsRelPath; +} + +/** + * Build the `./test/browser/context` export entry and write its JS/d.ts shims. + * + * Vitest's package.json only exposes `./browser` (mapped to `./test/browser`). + * The migration rewrites `@vitest/browser/context` → + * `vite-plus/test/browser/context`, so we add this path with both runtime and + * type targets that re-export from `@vitest/browser/context`. + */ +async function createBrowserContextExport(testDistDir: string): Promise { + const dir = join(testDistDir, 'browser'); + await mkdir(dir, { recursive: true }); + await writeFile(join(dir, 'context.js'), `export * from '@vitest/browser/context';\n`); + await writeFile( + join(dir, 'context.d.ts'), + `import '@vitest/browser/context';\nexport * from '@vitest/browser/context';\n`, + ); + return { + types: './dist/test/browser/context.d.ts', + default: './dist/test/browser/context.js', + }; +} + /** * Inline-copy a browser-provider's upstream `.d.ts` file into `outDtsPath` and * rewrite vitest-related bare specifiers to relative paths inside the diff --git a/packages/cli/package.json b/packages/cli/package.json index 08d2ce5ac3..9f07eb9b94 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -179,10 +179,12 @@ "default": "./dist/test/browser/providers/playwright.js" }, "./test/browser-playwright/context": { - "types": "./dist/test/browser-playwright/context.d.ts" + "types": "./dist/test/browser-playwright/context.d.ts", + "default": "./dist/test/browser-playwright/context.js" }, "./test/browser/providers/playwright/context": { - "types": "./dist/test/browser/providers/playwright/context.d.ts" + "types": "./dist/test/browser/providers/playwright/context.d.ts", + "default": "./dist/test/browser/providers/playwright/context.js" }, "./test/browser-preview": { "types": "./dist/test/browser-preview.d.ts", @@ -193,10 +195,12 @@ "default": "./dist/test/browser/providers/preview.js" }, "./test/browser-preview/context": { - "types": "./dist/test/browser-preview/context.d.ts" + "types": "./dist/test/browser-preview/context.d.ts", + "default": "./dist/test/browser-preview/context.js" }, "./test/browser/providers/preview/context": { - "types": "./dist/test/browser/providers/preview/context.d.ts" + "types": "./dist/test/browser/providers/preview/context.d.ts", + "default": "./dist/test/browser/providers/preview/context.js" }, "./test/browser-webdriverio": { "types": "./dist/test/browser-webdriverio.d.ts", @@ -207,10 +211,16 @@ "default": "./dist/test/browser/providers/webdriverio.js" }, "./test/browser-webdriverio/context": { - "types": "./dist/test/browser-webdriverio/context.d.ts" + "types": "./dist/test/browser-webdriverio/context.d.ts", + "default": "./dist/test/browser-webdriverio/context.js" }, "./test/browser/providers/webdriverio/context": { - "types": "./dist/test/browser/providers/webdriverio/context.d.ts" + "types": "./dist/test/browser/providers/webdriverio/context.d.ts", + "default": "./dist/test/browser/providers/webdriverio/context.js" + }, + "./test/browser/context": { + "types": "./dist/test/browser/context.d.ts", + "default": "./dist/test/browser/context.js" } }, "scripts": { From 74a2c204fb9a0593b3eed3f1378b224bbc398e25 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 17:48:50 +0800 Subject: [PATCH 32/37] fix(migration): don't let initial install's failure mask final install success MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The initial install (pre-migration) is best-effort — migration proceeds regardless of its outcome, and the final install (with --force / --no-frozen-lockfile) is the authoritative recovery. But `handleInstallResult` was being called on both summaries and setting `process.exitCode` on either failure, so a successful final install was being clobbered by a failed initial install's exit code, making the migration look failed when it wasn't. Add a `propagateExitCode` opt-out and apply it to the initial call only. Both failures still get reported via `report.warnings`. --- packages/cli/src/migration/bin.ts | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/migration/bin.ts b/packages/cli/src/migration/bin.ts index d487468c89..decba1e5d3 100644 --- a/packages/cli/src/migration/bin.ts +++ b/packages/cli/src/migration/bin.ts @@ -473,6 +473,13 @@ function handleInstallResult( installSummary: CommandRunSummary, rootDir: string, report: MigrationReport, + // The pre-migration "initial" install is best-effort: the migration proceeds + // regardless of its outcome, and a post-migration "final" install runs with + // `--force` / `--no-frozen-lockfile` as the authoritative recovery. Only that + // final install's failure should flip `process.exitCode` so a successful + // recovery yields exit 0; the initial failure is still surfaced via + // `report.warnings` + the warn message. + options?: { propagateExitCode?: boolean }, ): number { if (installSummary.status === 'installed') { return installSummary.durationMs; @@ -482,7 +489,9 @@ function handleInstallResult( const message = `Dependency installation failed (exit code ${exitCode}). Run \`vp install\` manually in ${rootDir} to resync node_modules.`; warnMsg(message); report.warnings.push(message); - process.exitCode = exitCode; + if (options?.propagateExitCode !== false) { + process.exitCode = exitCode; + } return 0; } return 0; @@ -819,15 +828,23 @@ async function executeMigrationPlan( ); clearMigrationProgress(); + // Process the initial install first so the final install's exit code "wins": + // if the initial install failed but the final install succeeded, the + // migration should still report success (exit 0). The initial call opts out + // of exitCode propagation; only the final call may flip process.exitCode. + const initialInstallDurationMs = handleInstallResult( + initialInstallSummary, + workspaceInfo.rootDir, + report, + { propagateExitCode: false }, + ); const finalInstallDurationMs = handleInstallResult( finalInstallSummary, workspaceInfo.rootDir, report, ); return { - installDurationMs: - handleInstallResult(initialInstallSummary, workspaceInfo.rootDir, report) + - finalInstallDurationMs, + installDurationMs: initialInstallDurationMs + finalInstallDurationMs, packageManagerVersion: downloadResult.version, report, }; From 66a0f82eaf276edff33834c6d8ce598855731308 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 17:48:56 +0800 Subject: [PATCH 33/37] ci(test-vp-create): include vitest family in VP_OVERRIDE_PACKAGES The env var replaces VITE_PLUS_OVERRIDE_PACKAGES entirely, so the CI's previous map (which only listed vite + vite-plus-core) left created projects with a catalog missing every vitest entry. Mirror the vitest family from ecosystem-ci/patch-project.ts so installs succeed. --- .github/workflows/test-vp-create.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-vp-create.yml b/.github/workflows/test-vp-create.yml index 155438725f..c5f53a5b4e 100644 --- a/.github/workflows/test-vp-create.yml +++ b/.github/workflows/test-vp-create.yml @@ -211,7 +211,7 @@ jobs: - name: Run vp create ${{ matrix.template.name }} with ${{ matrix.package-manager }} working-directory: ${{ runner.temp }} env: - VP_OVERRIDE_PACKAGES: '{"vite":"file:${{ github.workspace }}/tmp/tgz/${{ env.VITE_OVERRIDE_TGZ }}","@voidzero-dev/vite-plus-core":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz"}' + VP_OVERRIDE_PACKAGES: '{"vite":"file:${{ github.workspace }}/tmp/tgz/${{ env.VITE_OVERRIDE_TGZ }}","@voidzero-dev/vite-plus-core":"file:${{ github.workspace }}/tmp/tgz/voidzero-dev-vite-plus-core-0.0.0.tgz","vitest":"4.1.5","@vitest/expect":"4.1.5","@vitest/runner":"4.1.5","@vitest/snapshot":"4.1.5","@vitest/spy":"4.1.5","@vitest/utils":"4.1.5","@vitest/mocker":"4.1.5","@vitest/pretty-format":"4.1.5","@vitest/coverage-v8":"4.1.5","@vitest/coverage-istanbul":"4.1.5"}' run: | vp create ${{ matrix.template.create-args }} \ --no-interactive \ From a9777183e7f7063b9a81d8d510b0865a82176037 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 17:49:03 +0800 Subject: [PATCH 34/37] chore: keep VITEST_VERSION + @vitest/browser* catalog in sync on bumps - upgrade-deps.ts now bumps the @vitest/browser, @vitest/browser-playwright, @vitest/browser-preview, @vitest/browser-webdriverio catalog entries alongside the vitest line, and rewrites the VITEST_VERSION constant in packages/cli/src/utils/constants.ts. - ecosystem-ci/patch-project.ts imports VITEST_VERSION from the CLI constants so the three places that previously hardcoded "4.1.5" collapse to a single source of truth (constants.ts). --- .github/scripts/upgrade-deps.ts | 39 +++++++++++++++++++++++++++++++++ ecosystem-ci/patch-project.ts | 3 +-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/.github/scripts/upgrade-deps.ts b/.github/scripts/upgrade-deps.ts index bc478f4914..fdbabd5429 100644 --- a/.github/scripts/upgrade-deps.ts +++ b/.github/scripts/upgrade-deps.ts @@ -152,6 +152,18 @@ async function updatePnpmWorkspace(versions: PnpmWorkspaceVersions): Promise ({ + name: pkg, + pattern: new RegExp(`'${pkg.replace('/', '\\/')}': ([\\d.]+(?:-[\\w.]+)?)`), + replacement: `'${pkg}': ${versions.vitest}`, + newVersion: versions.vitest, + })); const entries: PnpmWorkspaceEntry[] = [ { name: 'vitest', @@ -164,6 +176,7 @@ async function updatePnpmWorkspace(versions: PnpmWorkspaceVersions): Promise { + const filePath = path.join(ROOT, 'packages/cli/src/utils/constants.ts'); + const content = fs.readFileSync(filePath, 'utf8'); + const pattern = /export const VITEST_VERSION = '([\d.]+(?:-[\w.]+)?)';/; + let oldVersion: string | undefined; + const updated = content.replace(pattern, (_match: string, captured: string) => { + oldVersion = captured; + return `export const VITEST_VERSION = '${vitestVersion}';`; + }); + if (oldVersion === undefined) { + throw new Error( + `Failed to match VITEST_VERSION in ${filePath} — the pattern ${pattern} is stale, ` + + `please update it in .github/scripts/upgrade-deps.ts`, + ); + } + fs.writeFileSync(filePath, updated); + recordChange('VITEST_VERSION constant', oldVersion, vitestVersion); + console.log('Updated packages/cli/src/utils/constants.ts'); +} + // ============ Update packages/core/package.json ============ async function updateCorePackage(devtoolsVersion: string): Promise { const filePath = path.join(ROOT, 'packages/core/package.json'); @@ -405,6 +443,7 @@ await updatePnpmWorkspace({ oxcParser: oxcParserVersion, oxcTransform: oxcTransformVersion, }); +await updateVitestVersionConstant(vitestVersion); await updateCorePackage(devtoolsVersion); writeMetaFiles(); diff --git a/ecosystem-ci/patch-project.ts b/ecosystem-ci/patch-project.ts index 0a178c4dec..4a8c626c14 100644 --- a/ecosystem-ci/patch-project.ts +++ b/ecosystem-ci/patch-project.ts @@ -2,6 +2,7 @@ import { execSync } from 'node:child_process'; import { readFile, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; +import { VITEST_VERSION } from '../packages/cli/src/utils/constants.ts'; import { ecosystemCiDir, tgzDir } from './paths.ts'; import repos from './repo.json' with { type: 'json' }; @@ -57,8 +58,6 @@ const forceFreshMigration = 'forceFreshMigration' in repoConfig && repoConfig.fo const isBunProject = project === 'bun-vite-template'; const viteOverrideTgz = isBunProject ? `vite-7.99.0.tgz` : `voidzero-dev-vite-plus-core-0.0.0.tgz`; -// Keep in sync with VITEST_VERSION in packages/cli/src/utils/constants.ts. -const VITEST_VERSION = '4.1.5'; const vitestOverrides = { vitest: VITEST_VERSION, '@vitest/expect': VITEST_VERSION, From 491e5325d3886c15f72d928d98708ce2bcf3961b Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 17:55:20 +0800 Subject: [PATCH 35/37] fix(cli): use es-module-lexer to scope vite-plus/test rewrites to real imports The previous regex-only rewriter ran on raw source text and would mutate string content that happened to contain `from 'vite-plus/test'` (template literals, error messages, fixtures). Switch the ESM import/dynamic-import path to es-module-lexer so only actual import specifiers get spliced. CJS `require()` keeps a tightened boundary-anchored regex. Added 4 unit tests covering the false-positive cases. --- packages/cli/package.json | 1 + .../define-config-mocker-rewrite.spec.ts | 55 +++++++++++++++++ packages/cli/src/define-config.ts | 60 +++++++++++++++++-- pnpm-lock.yaml | 3 + 4 files changed, 114 insertions(+), 5 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 9f07eb9b94..b535a2ef2a 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -241,6 +241,7 @@ "@vitest/browser-preview": "catalog:", "@vitest/browser-webdriverio": "catalog:", "@voidzero-dev/vite-plus-core": "workspace:*", + "es-module-lexer": "^1.7.0", "oxfmt": "catalog:", "oxlint": "catalog:", "oxlint-tsgolint": "catalog:", diff --git a/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts b/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts index 1e6782e12a..5c53e73997 100644 --- a/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts +++ b/packages/cli/src/__tests__/define-config-mocker-rewrite.spec.ts @@ -80,6 +80,61 @@ describe('rewriteVitePlusTestSpecifier', () => { ].join('\n'); expect(rewriteVitePlusTestSpecifier(input)).toBe(expected); }); + + it("does NOT rewrite `from 'vite-plus/test'` inside a template literal", () => { + const input = [ + "import { it } from 'vite-plus/test';", + "const fixture = `import { vi } from 'vite-plus/test'`;", + 'it("snapshots fixture", () => { console.log(fixture); });', + '', + ].join('\n'); + const expected = [ + "import { it } from 'vitest';", + "const fixture = `import { vi } from 'vite-plus/test'`;", + 'it("snapshots fixture", () => { console.log(fixture); });', + '', + ].join('\n'); + expect(rewriteVitePlusTestSpecifier(input)).toBe(expected); + }); + + it('does NOT rewrite the pattern inside a plain string-literal error message', () => { + const input = [ + "import { expect, it } from 'vite-plus/test';", + "it('reports the bad specifier', () => {", + ' const message = "Cannot resolve \'vite-plus/test\'";', + " expect(message).toContain('vite-plus/test');", + '});', + '', + ].join('\n'); + const expected = [ + "import { expect, it } from 'vitest';", + "it('reports the bad specifier', () => {", + ' const message = "Cannot resolve \'vite-plus/test\'";', + " expect(message).toContain('vite-plus/test');", + '});', + '', + ].join('\n'); + expect(rewriteVitePlusTestSpecifier(input)).toBe(expected); + }); + + it('does NOT rewrite the pattern inside a line/block comment or string concat', () => { + const input = [ + "// Reads 'vite-plus/test' off the import map and rewrites it", + "/* require('vite-plus/test') is the CJS form */", + "const composed = 'vite-' + 'plus/test';", + 'const literal = \'require("vite-plus/test")\';', + 'console.log(composed, literal);', + '', + ].join('\n'); + // None of these are real imports — output should be byte-identical. + expect(rewriteVitePlusTestSpecifier(input)).toBe(input); + }); + + it("rewrites a real `import { vi } from 'vite-plus/test'` statement", () => { + const input = ["import { vi } from 'vite-plus/test';", "vi.mock('./foo');", ''].join('\n'); + const expected = ["import { vi } from 'vitest';", "vi.mock('./foo');", ''].join('\n'); + expect(rewriteVitePlusTestSpecifier(input)).toBe(expected); + }); }); describe('defineConfig project plugin injection', () => { diff --git a/packages/cli/src/define-config.ts b/packages/cli/src/define-config.ts index fe3f49c707..c9308d79a2 100644 --- a/packages/cli/src/define-config.ts +++ b/packages/cli/src/define-config.ts @@ -1,4 +1,5 @@ import type { PluginOption, UserConfig } from '@voidzero-dev/vite-plus-core'; +import { initSync, parse, type ImportSpecifier } from 'es-module-lexer'; import type { OxfmtConfig } from 'oxfmt'; import type { OxlintConfig } from 'oxlint'; import { @@ -74,16 +75,65 @@ type ViteUserConfigExport = * Task #50 pins `vitest` and the `@vitest/*` family so both specifiers resolve * to the same physical module, making this rewrite runtime-safe. * + * Uses `es-module-lexer` so only real ESM `import`/`export ... from` and + * dynamic `import()` specifiers are touched — string literals, template + * literals, and error messages that happen to contain `vite-plus/test` are + * left alone. CommonJS `require(...)` calls are handled separately by a + * tightened regex (es-module-lexer is ESM-only). + * * Exported for unit testing. */ +const TARGET_SPECIFIER = 'vite-plus/test'; +const TARGET_REPLACEMENT = 'vitest'; + +// Tightened CJS require regex. The lookbehind `(?<=[\s;{}(\[,=])` ensures the +// `require` keyword sits at a statement-ish boundary, which keeps it from +// matching `.require(...)` member calls or `'require(' + path + ')'`-style +// string content. Note: this still can match inside multi-line template +// literals or strings that contain raw newlines + boundary chars, but those +// cases were not covered by the original regex either; the ESM lexer pass +// above already eliminates the common false positives that motivated this fix. +const REQUIRE_PATTERN = /(?<=^|[\s;{}([,=])(require\s*\(\s*['"])vite-plus\/test(?=['"])/g; + +let esLexerInitialized = false; +function ensureLexerInit(): void { + if (esLexerInitialized) { + return; + } + initSync(); + esLexerInitialized = true; +} + export function rewriteVitePlusTestSpecifier(code: string): string { - if (!code.includes('vite-plus/test')) { + if (!code.includes(TARGET_SPECIFIER)) { return code; } - return code - .replace(/(from\s+['"])vite-plus\/test(?=['"])/g, '$1vitest') - .replace(/(import\s*\(\s*['"])vite-plus\/test(?=['"])/g, '$1vitest') - .replace(/(require\s*\(\s*['"])vite-plus\/test(?=['"])/g, '$1vitest'); + + // Step 1: rewrite ESM static/dynamic imports via es-module-lexer. + let result = code; + let imports: ReadonlyArray | undefined; + try { + ensureLexerInit(); + [imports] = parse(code); + } catch { + // Parse failure (non-JS file, syntax error before transformation, etc.): + // skip the ESM-aware pass and let the CJS regex still run below. + imports = undefined; + } + + if (imports && imports.length > 0) { + // Walk in reverse so earlier offsets stay valid as we splice. + const matches = imports.filter((i) => i.n === TARGET_SPECIFIER); + for (let i = matches.length - 1; i >= 0; i--) { + const { s, e } = matches[i]; + result = result.slice(0, s) + TARGET_REPLACEMENT + result.slice(e); + } + } + + // Step 2: rewrite CJS require() calls (not seen by es-module-lexer). + result = result.replace(REQUIRE_PATTERN, `$1${TARGET_REPLACEMENT}`); + + return result; } function vitePlusTestSpecifierRewritePlugin(): PluginOption { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c84e36c65c..fd417ff5b7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -369,6 +369,9 @@ importers: '@voidzero-dev/vite-plus-core': specifier: workspace:* version: link:../core + es-module-lexer: + specifier: ^1.7.0 + version: 1.7.0 oxfmt: specifier: 'catalog:' version: 0.48.0 From 1a5b2697e5f2f40cd224835801dbf585e084ae15 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 17:58:26 +0800 Subject: [PATCH 36/37] fix(migration): pin legacy wrapper fallback to exact VITEST_VERSION `LEGACY_WRAPPER_FALLBACK_VERSIONS.vitest` was set to `^${VITEST_VERSION}`, while fresh migrations write the exact `VITEST_VERSION` via `VITE_PLUS_OVERRIDE_PACKAGES`. Projects cleaned up from a stale `@voidzero-dev/vite-plus-test` alias should land on the same exact pin as fresh migrations, not a caret range that allows unintended drift on reinstall. --- packages/cli/src/migration/migrator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/migration/migrator.ts b/packages/cli/src/migration/migrator.ts index 8bc288fabb..fea03555e4 100644 --- a/packages/cli/src/migration/migrator.ts +++ b/packages/cli/src/migration/migrator.ts @@ -109,7 +109,7 @@ const LEGACY_WRAPPER_PACKAGE_NAMES = ['@voidzero-dev/vite-plus-test'] as const; // rewritten. For `vitest`, we substitute the vitest version vite-plus // bundles so any `catalog:` reference the user still has resolves cleanly. const LEGACY_WRAPPER_FALLBACK_VERSIONS: Record = { - vitest: `^${VITEST_VERSION}`, + vitest: VITEST_VERSION, }; function isLegacyWrapperSpec(value: string | undefined): boolean { From acbb9e832b51183e1fc34c60514629be5955bfaf Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 16 May 2026 22:01:27 +0800 Subject: [PATCH 37/37] chore(upgrade-deps): bump vitest pins in test-vp-create.yml too The workflow's VP_OVERRIDE_PACKAGES JSON hardcodes the vitest family at "4.1.5" ten times. Without rewriting this file on bump, CI's vp create tests pin a stale vitest version after the next daily upgrade. Add updateTestVpCreateWorkflow alongside the constants.ts + pnpm-workspace.yaml rewrites. --- .github/scripts/upgrade-deps.ts | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/.github/scripts/upgrade-deps.ts b/.github/scripts/upgrade-deps.ts index fdbabd5429..909a83cda8 100644 --- a/.github/scripts/upgrade-deps.ts +++ b/.github/scripts/upgrade-deps.ts @@ -289,6 +289,45 @@ async function updateVitestVersionConstant(vitestVersion: string): Promise console.log('Updated packages/cli/src/utils/constants.ts'); } +// ============ Update .github/workflows/test-vp-create.yml ============ +// The `vp create` smoke-test workflow pins every vitest-family package via the +// `VP_OVERRIDE_PACKAGES` env var so that template installs use the bundled +// version. Daily upstream bumps must rewrite those pins so the workflow does +// not drift behind the rest of the repo. +async function updateTestVpCreateWorkflow(vitestVersion: string): Promise { + const filePath = path.join(ROOT, '.github/workflows/test-vp-create.yml'); + const content = fs.readFileSync(filePath, 'utf8'); + const vitestKeys = [ + 'vitest', + '@vitest/expect', + '@vitest/runner', + '@vitest/snapshot', + '@vitest/spy', + '@vitest/utils', + '@vitest/mocker', + '@vitest/pretty-format', + '@vitest/coverage-v8', + '@vitest/coverage-istanbul', + ]; + let updated = content; + for (const key of vitestKeys) { + const pattern = new RegExp(`"${key.replace('/', '\\/')}":"([\\d.]+(?:-[\\w.]+)?)"`); + let matched = false; + updated = updated.replace(pattern, (_match: string, _captured: string) => { + matched = true; + return `"${key}":"${vitestVersion}"`; + }); + if (!matched) { + throw new Error( + `Failed to match "${key}" in ${filePath} — the pattern ${pattern} is stale, ` + + `please update it in .github/scripts/upgrade-deps.ts`, + ); + } + } + fs.writeFileSync(filePath, updated); + console.log('Updated .github/workflows/test-vp-create.yml'); +} + // ============ Update packages/core/package.json ============ async function updateCorePackage(devtoolsVersion: string): Promise { const filePath = path.join(ROOT, 'packages/core/package.json'); @@ -444,6 +483,7 @@ await updatePnpmWorkspace({ oxcTransform: oxcTransformVersion, }); await updateVitestVersionConstant(vitestVersion); +await updateTestVpCreateWorkflow(vitestVersion); await updateCorePackage(devtoolsVersion); writeMetaFiles();