Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
b4dd1a2
refactor: replace @voidzero-dev/vite-plus-test with upstream vitest@4…
Brooooooklyn May 15, 2026
0fca2b2
fix(migration): re-pin vite-plus in force-override mode, fix lint/for…
Brooooooklyn May 15, 2026
35bff67
fix(migration): pass --no-frozen-lockfile to pnpm/yarn reinstall afte…
Brooooooklyn May 15, 2026
47bc350
fix(migration): preserve vitest declare-module, route browser-provide…
Brooooooklyn May 15, 2026
4a06dbc
fix(migration): emit bunfig.toml with peer = false to unblock bun ins…
Brooooooklyn May 15, 2026
ddd2f09
docs: align migrate guide and bundling notes with actual rewrite/shim…
Brooooooklyn May 15, 2026
cc25ff0
fix(ci): bump core tgz version for bun, sync declare-module snap
Brooooooklyn May 15, 2026
fab9ff2
fix(ci): use a separate bumped-version core tgz for VP_OVERRIDE_PACKAGES
Brooooooklyn May 15, 2026
24d3f80
fix(ci): pack core/cli with synthetic 7.99.0 version for bun peer-dep
Brooooooklyn May 16, 2026
c98bacc
docs(cli): reformat BUNDLING.md provider-exports table
Brooooooklyn May 16, 2026
0b7129e
fix(migration): mirror vite override as devDep on bun
Brooooooklyn May 16, 2026
92f3022
fix(ci): pack a vite-7.99.0.tgz alias so bun's name+version check passes
Brooooooklyn May 16, 2026
40a7165
fix(ci): post-process core tgz into vite alias instead of name-swappi…
Brooooooklyn May 16, 2026
a53ca1e
fix(ci): use core tgz for vite override except where bun is the target
Brooooooklyn May 16, 2026
5c8d31d
chore: vp check --fix
Brooooooklyn May 16, 2026
a9c3b54
fix(migration): override vitest + @vitest/* family to single version
Brooooooklyn May 16, 2026
b205b92
fix(cli): accept `test` field in defineConfig type signature
Brooooooklyn May 16, 2026
293affd
fix(cli): inject vitest specifier rewrite plugin into defineConfig
Brooooooklyn May 16, 2026
15c82da
fix(cli): resolve mergeConfig star-export conflict between core and v…
Brooooooklyn May 16, 2026
9349ef8
test(snap): redact transient network warnings in snap output
Brooooooklyn May 16, 2026
675a4a1
fix(migration): override @vitest/coverage-* family
Brooooooklyn May 16, 2026
fa44cd2
fix(migration): rewrite `from 'vite-plus/test'` -> `from 'vitest'`
Brooooooklyn May 16, 2026
c843ac3
style(migration): cargo fmt
Brooooooklyn May 16, 2026
132b038
revert(migration): restore `'vitest' -> 'vite-plus/test'` forward rew…
Brooooooklyn May 16, 2026
418bdbf
chore: retrigger CI after empty period
Brooooooklyn May 16, 2026
19cef84
fix(cli): re-export vitest/config types (ViteUserConfig, etc.)
Brooooooklyn May 16, 2026
a174279
test(snap): drop leading whitespace on pnpm10 Packages line
Brooooooklyn May 16, 2026
f32a3ba
fix(cli): propagate vite-plus/test rewrite plugin into test.projects
Brooooooklyn May 16, 2026
7b6d427
chore: apply oxfmt formatting
Brooooooklyn May 16, 2026
6e70ed8
fix(cli): drop redundant type assertions in project injector
Brooooooklyn May 16, 2026
d182b0b
fix(cli): add runtime targets for browser provider context exports
Brooooooklyn May 16, 2026
3778e7b
fix(migration): don't let initial install's failure mask final instal…
Brooooooklyn May 16, 2026
54000a2
ci(test-vp-create): include vitest family in VP_OVERRIDE_PACKAGES
Brooooooklyn May 16, 2026
a653161
chore: keep VITEST_VERSION + @vitest/browser* catalog in sync on bumps
Brooooooklyn May 16, 2026
5624d18
fix(cli): use es-module-lexer to scope vite-plus/test rewrites to rea…
Brooooooklyn May 16, 2026
d1af03d
fix(migration): pin legacy wrapper fallback to exact VITEST_VERSION
Brooooooklyn May 16, 2026
acd2ab6
chore(upgrade-deps): bump vitest pins in test-vp-create.yml too
Brooooooklyn May 16, 2026
d82a392
fix(cli): preserve quotes when rewriting dynamic import specifiers
Brooooooklyn May 18, 2026
a15f64b
fix(deps): patch @vitest/mocker to hoist vite-plus/test imports
Brooooooklyn May 18, 2026
5a43b83
fix(cli): fall back to regex rewrite when es-module-lexer rejects JSX…
Brooooooklyn May 18, 2026
2e49a76
fix(cli): restore missing test/* subpaths and auto-inline matcher pac…
Brooooooklyn May 18, 2026
857321c
style: format build.ts and define-config.ts to oxfmt rules
Brooooooklyn May 18, 2026
efc91f2
fix(cli): align CJS index.cts allowlist with ESM index.ts
Brooooooklyn May 18, 2026
eaa3344
style(cli): apply vp check --fix to define-config.ts and build.ts
Brooooooklyn May 18, 2026
aef23cf
fix(cli): use oxc-parser for TSX rewrite fallback, cover re-exports
Brooooooklyn May 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 80 additions & 27 deletions .github/scripts/upgrade-deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,31 @@ async function updatePnpmWorkspace(versions: PnpmWorkspaceVersions): Promise<voi
let content = fs.readFileSync(filePath, 'utf8');

// oxlint's trailing \n in the pattern disambiguates from oxlint-tsgolint.
const vitestBrowserPackages = [
'@vitest/browser',
'@vitest/browser-playwright',
'@vitest/browser-preview',
'@vitest/browser-webdriverio',
];
const vitestBrowserEntries: PnpmWorkspaceEntry[] = vitestBrowserPackages.map((pkg) => ({
name: pkg,
pattern: new RegExp(`'${pkg.replace('/', '\\/')}': ([\\d.]+(?:-[\\w.]+)?)`),
replacement: `'${pkg}': ${versions.vitest}`,
newVersion: versions.vitest,
}));
Comment thread
Brooooooklyn marked this conversation as resolved.
const entries: PnpmWorkspaceEntry[] = [
{
name: 'vitest',
pattern: /vitest-dev: npm:vitest@\^([\d.]+(?:-[\w.]+)?)/,
replacement: `vitest-dev: npm:vitest@^${versions.vitest}`,
// The `@voidzero-dev/vite-plus-test` wrapper (which used to be aliased
// here via `vitest-dev: npm:vitest@^…`) has been removed. Vitest is now
// a plain catalog entry pinned to an exact version (`vitest: x.y.z`),
// so match that shape directly. The leading newline anchor disambiguates
// from neighbouring keys like `vitepress-*` and `@vitest/browser`.
pattern: /\n {2}vitest: ([\d.]+(?:-[\w.]+)?)\n/,
replacement: `\n vitest: ${versions.vitest}\n`,
Comment thread
Brooooooklyn marked this conversation as resolved.
Comment thread
cursor[bot] marked this conversation as resolved.
newVersion: versions.vitest,
},
...vitestBrowserEntries,
{
name: 'tsdown',
pattern: /tsdown: \^([\d.]+(?:-[\w.]+)?)/,
Expand Down Expand Up @@ -246,34 +264,68 @@ async function updatePnpmWorkspace(versions: PnpmWorkspaceVersions): Promise<voi
console.log('Updated pnpm-workspace.yaml');
}

// ============ Update packages/test/package.json ============
async function updateTestPackage(vitestVersion: string): Promise<void> {
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 VITEST_VERSION constant ============
// Keeps the TypeScript source-of-truth (`packages/cli/src/utils/constants.ts`)
// in sync with the `vitest:` catalog entry in pnpm-workspace.yaml. The
// constant is consumed by both `packages/cli` and `ecosystem-ci/patch-project.ts`
// (which re-imports it), so daily upstream bumps must update it here too.
async function updateVitestVersionConstant(vitestVersion: string): Promise<void> {
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 all @vitest/* devDependencies
for (const dep of Object.keys(devDependencies)) {
if (dep.startsWith('@vitest/')) {
devDependencies[dep] = vitestVersion;
// ============ 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<void> {
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`,
);
}
}

// 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');
fs.writeFileSync(filePath, updated);
console.log('Updated .github/workflows/test-vp-create.yml');
}

// ============ Update packages/core/package.json ============
Expand Down Expand Up @@ -430,7 +482,8 @@ await updatePnpmWorkspace({
oxcParser: oxcParserVersion,
oxcTransform: oxcTransformVersion,
});
await updateTestPackage(vitestVersion);
await updateVitestVersionConstant(vitestVersion);
await updateTestVpCreateWorkflow(vitestVersion);
await updateCorePackage(devtoolsVersion);

writeMetaFiles();
Expand Down
20 changes: 19 additions & 1 deletion .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +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/test && 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`,
# not `vite`) and the version check (0.0.0 is outside `^6|^7|^8`).
# 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.
#
# 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
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/prepare_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/publish-to-pkg.pr.new.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,4 @@ jobs:
'./packages/cli/cli-npm/*' \
'./packages/cli' \
'./packages/core' \
'./packages/prompts' \
'./packages/test'
'./packages/prompts'
3 changes: 0 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,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
Expand All @@ -170,7 +169,6 @@ jobs:
### Published Packages

- \`@voidzero-dev/vite-plus-core@${VERSION}\`
- \`@voidzero-dev/vite-plus-test@${VERSION}\`
- \`vite-plus@${VERSION}\`

### Installation
Expand Down Expand Up @@ -219,7 +217,6 @@ jobs:

**Published Packages:**
• @voidzero-dev/vite-plus-core@${{ env.VERSION }}
• @voidzero-dev/vite-plus-test@${{ env.VERSION }}
• vite-plus@${{ env.VERSION }}

**Install:**
Expand Down
31 changes: 29 additions & 2 deletions .github/workflows/test-vp-create.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +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/test && 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`,
# not `vite`) and the version check (0.0.0 is outside `^6|^7|^8`).
# 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.
#
# 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@<version>"
# 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
Expand Down Expand Up @@ -152,7 +172,12 @@ 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"}'
# 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@<version> 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
Expand Down Expand Up @@ -185,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","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"}'
Comment thread
Brooooooklyn marked this conversation as resolved.
Comment thread
Brooooooklyn marked this conversation as resolved.
run: |
vp create ${{ matrix.template.create-args }} \
--no-interactive \
Expand Down
9 changes: 3 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
```

Expand All @@ -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"
}
```

Expand Down
6 changes: 1 addition & 5 deletions crates/vite_global_cli/src/commands/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
11 changes: 7 additions & 4 deletions crates/vite_migration/src/file_walker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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]
Expand Down
Loading
Loading