Skip to content

Commit 73887c8

Browse files
committed
fix(test): rewrite vitest self-references in globals.d.ts for type-aware linting
The bundled globals.d.ts declares types like `typeof import('vitest')['test']`, but `vitest` is not resolvable from the @voidzero-dev/vite-plus-test package context in pnpm's strict node_modules layout. TypeScript silently treats the unresolved import as `any`, but oxlint's type-aware linting treats it as an `error` type, causing `no-unsafe-call` errors. Fix by rewriting `import('vitest')` to `import('@voidzero-dev/vite-plus-test')` during the bundleVitest() copy step, making it a self-reference that resolves correctly via Node.js package self-referencing. Also adds the vite-plus-vitest-global-type-minimal-repro project to ecosystem-ci.
1 parent 97c7571 commit 73887c8

4 files changed

Lines changed: 19 additions & 1 deletion

File tree

.github/workflows/e2e-test.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,11 @@ jobs:
294294
command: |
295295
vp fmt
296296
vp run validate
297+
- name: vite-plus-vitest-global-type-minimal-repro
298+
node-version: 24
299+
command: |
300+
vp test
301+
vp check --fix
297302
exclude:
298303
# frm-stack uses Docker (testcontainers) which doesn't work the same way on Windows
299304
- os: windows-latest

ecosystem-ci/repo.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,5 +102,11 @@
102102
"repository": "https://github.com/why-reproductions-are-required/bun-vite-template.git",
103103
"branch": "master",
104104
"hash": "d84099b4a153c7e0f35e510725b2ceb24c6e09ad"
105+
},
106+
"vite-plus-vitest-global-type-minimal-repro": {
107+
"repository": "https://github.com/why-reproductions-are-required/vite-plus-vitest-global-type-minimal-repro.git",
108+
"branch": "main",
109+
"hash": "419653665e4f0688ad3cac68a34673fdd0632b55",
110+
"forceFreshMigration": true
105111
}
106112
}

packages/test/BUNDLING.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,12 @@ For maintainers developing the vitest/vite migration feature, here are the trans
113113
| `from "@vitest/browser-preview"` | `from "@voidzero-dev/vite-plus-test/browser-preview"` |
114114
| `from "vite"` | `from "@voidzero-dev/vite-plus-core"` |
115115
| `from "vite/module-runner"` | `from "@voidzero-dev/vite-plus-core/module-runner"` |
116+
| `import('vitest')` | `import('@voidzero-dev/vite-plus-test')` |
116117

117118
**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.
118119

120+
**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.
121+
119122
**Note:** When using pnpm overrides, you have three options for browser provider imports:
120123

121124
- `vitest/browser-playwright` (or `vitest/browser-webdriverio`, `vitest/browser-preview`) - works when `vitest` is overridden to our package (Recommended)

packages/test/build.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ const distDir = resolve(projectDir, 'dist');
6565
const vendorDir = resolve(distDir, 'vendor');
6666

6767
const CORE_PACKAGE_NAME = '@voidzero-dev/vite-plus-core';
68+
const TEST_PACKAGE_NAME = '@voidzero-dev/vite-plus-test';
6869

6970
// @vitest/* packages to copy (not bundle) to preserve browser/Node.js separation
7071
// These are copied from node_modules to dist/@vitest/ to avoid shared chunks
@@ -480,7 +481,10 @@ async function bundleVitest() {
480481
.replaceAll(/require\("vite"\)/g, `require("${CORE_PACKAGE_NAME}")`)
481482
.replaceAll(`import 'vite';`, `import '${CORE_PACKAGE_NAME}';`)
482483
.replaceAll(`'vite/module-runner'`, `'${CORE_PACKAGE_NAME}/module-runner'`)
483-
.replaceAll(`declare module "vite"`, `declare module "${CORE_PACKAGE_NAME}"`);
484+
.replaceAll(`declare module "vite"`, `declare module "${CORE_PACKAGE_NAME}"`)
485+
// Rewrite vitest self-references in .d.ts files (e.g., globals.d.ts uses
486+
// `typeof import('vitest')['test']` which must resolve via self-reference)
487+
.replaceAll(/import\(['"]vitest['"]\)/g, `import('${TEST_PACKAGE_NAME}')`);
484488
console.log(`Replaced vite imports in ${destPath}`);
485489
await writeFile(destPath, content, 'utf-8');
486490
} else {

0 commit comments

Comments
 (0)