Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,11 @@ jobs:
command: |
vp fmt
vp run validate
- name: vite-plus-vitest-global-type-minimal-repro
node-version: 24
command: |
vp test
vp check --fix
exclude:
# frm-stack uses Docker (testcontainers) which doesn't work the same way on Windows
- os: windows-latest
Expand Down
6 changes: 6 additions & 0 deletions ecosystem-ci/repo.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,11 @@
"repository": "https://github.com/why-reproductions-are-required/bun-vite-template.git",
"branch": "master",
"hash": "d84099b4a153c7e0f35e510725b2ceb24c6e09ad"
},
"vite-plus-vitest-global-type-minimal-repro": {
"repository": "https://github.com/why-reproductions-are-required/vite-plus-vitest-global-type-minimal-repro.git",
"branch": "main",
"hash": "419653665e4f0688ad3cac68a34673fdd0632b55",
"forceFreshMigration": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "check-vitest-globals-typecheck",
"version": "0.0.0",
"private": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
> vp check
pass: All 6 files are correctly formatted (<variable>ms, <variable> threads)
pass: Found no warnings, lint errors, or type errors in 3 files (<variable>ms, <variable> threads)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { fn } from "./index.ts";

test("fn", () => {
expect(fn()).toBe("Hello, world!");
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function fn() {
return "Hello, world!";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"env": {
"VITE_DISABLE_AUTO_INSTALL": "1"
},
"commands": ["vp check"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"moduleResolution": "nodenext",
"types": ["vite-plus/test/globals"],
"strict": true,
"noEmit": true,
"allowImportingTsExtensions": true,
"skipLibCheck": true
},
"include": ["src"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default {
test: {
globals: true,
},
lint: {
options: {
typeAware: true,
typeCheck: true,
},
rules: {
"typescript/no-unsafe-call": "error",
},
},
};
3 changes: 2 additions & 1 deletion packages/cli/src/migration/migrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,7 @@ export function rewriteStandaloneProject(
overrides: {
...pkg.pnpm?.overrides,
...VITE_PLUS_OVERRIDE_PACKAGES,
...(isForceOverrideMode() ? { [VITE_PLUS_NAME]: VITE_PLUS_VERSION } : {}),
},
};
// remove packages from `resolutions` field if they exist
Expand All @@ -734,7 +735,7 @@ export function rewriteStandaloneProject(
extractedStagedConfig = rewritePackageJson(pkg, packageManager, false, skipStagedMigration);

// ensure vite-plus is in devDependencies
if (!pkg.devDependencies?.[VITE_PLUS_NAME]) {
if (!pkg.devDependencies?.[VITE_PLUS_NAME] || isForceOverrideMode()) {
pkg.devDependencies = {
...pkg.devDependencies,
[VITE_PLUS_NAME]: VITE_PLUS_VERSION,
Expand Down
3 changes: 3 additions & 0 deletions packages/test/BUNDLING.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,12 @@ For maintainers developing the vitest/vite migration feature, here are the trans
| `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)
Expand Down
4 changes: 3 additions & 1 deletion packages/test/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ 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
Expand Down Expand Up @@ -480,7 +481,8 @@ async function bundleVitest() {
.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(`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 {
Expand Down
Loading