Skip to content

Commit 9ae77d1

Browse files
authored
Merge branch 'main' into feat/dynamic-completion
2 parents 62b6e8d + ab7f106 commit 9ae77d1

19 files changed

Lines changed: 451 additions & 105 deletions

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/cli/build.ts

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
* 3. buildNapiBinding() - Builds the native Rust binding via NAPI
88
* 4. syncCorePackageExports() - Creates shim files to re-export from @voidzero-dev/vite-plus-core
99
* 5. syncTestPackageExports() - Creates shim files to re-export from @voidzero-dev/vite-plus-test
10-
* 6. copySkillDocs() - Copies docs into skills/vite-plus/docs for runtime MCP access
11-
* 7. syncReadmeFromRoot() - Keeps package README in sync
10+
* 6. syncVersionsExport() - Generates ./versions module with bundled tool versions
11+
* 7. copySkillDocs() - Copies docs into skills/vite-plus/docs for runtime MCP access
12+
* 8. syncReadmeFromRoot() - Keeps package README in sync
1213
*
1314
* The sync functions allow this package to be a drop-in replacement for 'vite' by
1415
* re-exporting all the same subpaths (./client, ./types/*, etc.) while delegating
@@ -38,6 +39,8 @@ import {
3839
} from 'typescript';
3940

4041
import { generateLicenseFile } from '../../scripts/generate-license.ts';
42+
import corePkg from '../core/package.json' with { type: 'json' };
43+
import testPkg from '../test/package.json' with { type: 'json' };
4144

4245
const projectDir = dirname(fileURLToPath(import.meta.url));
4346
const TEST_PACKAGE_NAME = '@voidzero-dev/vite-plus-test';
@@ -80,6 +83,7 @@ if (!skipNative) {
8083
if (!skipTs) {
8184
await syncCorePackageExports();
8285
await syncTestPackageExports();
86+
await syncVersionsExport();
8387
}
8488
await copySkillDocs();
8589
await syncReadmeFromRoot();
@@ -425,6 +429,75 @@ async function syncTestPackageExports() {
425429
console.log(`\nSynced ${Object.keys(generatedExports).length} exports from test package`);
426430
}
427431

432+
/**
433+
* Read version from a dependency's package.json in node_modules.
434+
* Uses readFile because these packages don't export ./package.json.
435+
*
436+
* TODO: Once https://github.com/oxc-project/oxc/pull/20784 lands and oxlint/oxfmt/oxlint-tsgolint
437+
* export ./package.json, this function can be removed and replaced with static imports:
438+
* ```js
439+
* import oxlintPkg from 'oxlint/package.json' with { type: 'json' };
440+
* import oxfmtPkg from 'oxfmt/package.json' with { type: 'json' };
441+
* import oxlintTsgolintPkg from 'oxlint-tsgolint/package.json' with { type: 'json' };
442+
* ```
443+
*/
444+
async function readDepVersion(packageName: string): Promise<string | null> {
445+
try {
446+
const pkgPath = join(projectDir, 'node_modules', packageName, 'package.json');
447+
const pkg = JSON.parse(await readFile(pkgPath, 'utf-8'));
448+
return pkg.version ?? null;
449+
} catch {
450+
return null;
451+
}
452+
}
453+
454+
/**
455+
* Generate ./versions export module with bundled tool versions.
456+
*
457+
* Collects versions from:
458+
* - core/test package.json bundledVersions (vite, rolldown, tsdown, vitest)
459+
* - CLI dependency package.json (oxlint, oxfmt, oxlint-tsgolint)
460+
*
461+
* Generates dist/versions.js and dist/versions.d.ts with inlined constants.
462+
*/
463+
async function syncVersionsExport() {
464+
console.log('\nSyncing versions export...');
465+
const distDir = join(projectDir, 'dist');
466+
467+
// Collect versions from bundledVersions (core + test)
468+
const versions: Record<string, string> = {
469+
...(corePkg as Record<string, any>).bundledVersions,
470+
...(testPkg as Record<string, any>).bundledVersions,
471+
};
472+
473+
// Collect versions from CLI dependencies (oxlint, oxfmt, oxlint-tsgolint)
474+
// These don't export ./package.json, so we read from node_modules directly
475+
const depTools = ['oxlint', 'oxfmt', 'oxlint-tsgolint'] as const;
476+
for (const name of depTools) {
477+
const version = await readDepVersion(name);
478+
if (version) {
479+
versions[name] = version;
480+
}
481+
}
482+
483+
// dist/versions.js — inlined constants (no runtime I/O)
484+
await writeFile(
485+
join(distDir, 'versions.js'),
486+
`export const versions = ${JSON.stringify(versions, null, 2)};\n`,
487+
);
488+
489+
// dist/versions.d.ts — type declarations
490+
const typeFields = Object.keys(versions)
491+
.map((k) => ` readonly '${k}': string;`)
492+
.join('\n');
493+
await writeFile(
494+
join(distDir, 'versions.d.ts'),
495+
`export declare const versions: {\n${typeFields}\n};\n`,
496+
);
497+
498+
console.log(` Created ./versions (${Object.keys(versions).length} tools)`);
499+
}
500+
428501
/**
429502
* Copy markdown doc files from the monorepo docs/ directory into skills/vite-plus/docs/,
430503
* preserving the relative directory structure. This keeps stable file paths for

packages/cli/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@
7575
"types": "./dist/pack.d.ts",
7676
"import": "./dist/pack.js"
7777
},
78+
"./versions": {
79+
"types": "./dist/versions.d.ts",
80+
"default": "./dist/versions.js"
81+
},
7882
"./test": {
7983
"import": {
8084
"types": "./dist/test/index.d.ts",
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "check-vitest-globals-typecheck",
3+
"version": "0.0.0",
4+
"private": true
5+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
> vp check
2+
pass: All 6 files are correctly formatted (<variable>ms, <variable> threads)
3+
pass: Found no warnings, lint errors, or type errors in 3 files (<variable>ms, <variable> threads)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { fn } from "./index.ts";
2+
3+
test("fn", () => {
4+
expect(fn()).toBe("Hello, world!");
5+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function fn() {
2+
return "Hello, world!";
3+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"env": {
3+
"VITE_DISABLE_AUTO_INSTALL": "1"
4+
},
5+
"commands": ["vp check"]
6+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"compilerOptions": {
3+
"target": "esnext",
4+
"module": "nodenext",
5+
"moduleResolution": "nodenext",
6+
"types": ["vite-plus/test/globals"],
7+
"strict": true,
8+
"noEmit": true,
9+
"allowImportingTsExtensions": true,
10+
"skipLibCheck": true
11+
},
12+
"include": ["src"]
13+
}

0 commit comments

Comments
 (0)