11import { execSync } from 'node:child_process' ;
2- import fs from 'node:fs' ;
32import { dirname , join } from 'node:path' ;
43import { fileURLToPath } from 'node:url' ;
54
6- import vitestPackageJson from '../packages/test/package.json' with { type : 'json' } ;
75import repos from './repo.json' with { type : 'json' } ;
86
97const projectDir = dirname ( fileURLToPath ( import . meta. url ) ) ;
@@ -19,196 +17,6 @@ if (!projects.includes(project)) {
1917
2018const tgzPath = join ( projectDir , '..' , 'tmp' , 'tgz' ) ;
2119
22- async function patchVibeDashboard ( ) {
23- const pnpmWorkspacePath = join ( projectDir , 'vibe-dashboard' , 'pnpm-workspace.yaml' ) ;
24- const pnpmWorkspaceFile = fs
25- . readFileSync ( pnpmWorkspacePath , 'utf8' )
26- . replace (
27- '"vite": "npm:@voidzero-dev/vite-plus-core"' ,
28- `"vite": "file:${ tgzPath } /voidzero-dev-vite-plus-core-0.0.0.tgz"` ,
29- )
30- . replace (
31- '"vitest": "npm:@voidzero-dev/vite-plus-test"' ,
32- `"vitest": "file:${ tgzPath } /voidzero-dev-vite-plus-test-0.0.0.tgz"
33- "@vitest/browser": "file:${ tgzPath } /voidzero-dev-vite-plus-test-0.0.0.tgz"
34- "@vitest/browser-playwright": "file:${ tgzPath } /voidzero-dev-vite-plus-test-0.0.0.tgz"
35- "@voidzero-dev/vite-plus": "file:${ tgzPath } /voidzero-dev-vite-plus-0.0.0.tgz"
36- "@voidzero-dev/vite-plus-core": "file:${ tgzPath } /voidzero-dev-vite-plus-core-0.0.0.tgz"
37- "@voidzero-dev/vite-plus-test": "file:${ tgzPath } /voidzero-dev-vite-plus-test-0.0.0.tgz"` ,
38- ) ;
39- fs . writeFileSync ( pnpmWorkspacePath , pnpmWorkspaceFile ) ;
40-
41- // Remove @vitest /* packages from apps/dashboard/package.json
42- // These are bundled into our vitest package and shouldn't be installed separately
43- const dashboardPackageJsonPath = join (
44- projectDir ,
45- 'vibe-dashboard' ,
46- 'apps' ,
47- 'dashboard' ,
48- 'package.json' ,
49- ) ;
50- const dashboardPackageJson = JSON . parse ( fs . readFileSync ( dashboardPackageJsonPath , 'utf8' ) ) ;
51- if ( dashboardPackageJson . devDependencies ) {
52- // Remove @vitest /browser, @vitest/ui, and @vitest/browser-playwright
53- // They're all bundled in our vitest package now
54- const vitestPackagesToRemove = [ '@vitest/browser' , '@vitest/ui' , '@vitest/browser-playwright' ] ;
55- for ( const pkg of vitestPackagesToRemove ) {
56- delete dashboardPackageJson . devDependencies [ pkg ] ;
57- }
58- }
59-
60- // Note: @vitest /* packages are now bundled into our vitest package, so we don't need
61- // to add them as separate devDependencies anymore.
62-
63- // Write the updated package.json
64- fs . writeFileSync ( dashboardPackageJsonPath , JSON . stringify ( dashboardPackageJson , null , 2 ) + '\n' ) ;
65-
66- // Update vite.config.ts to import from vitest/browser-playwright instead of @vitest/browser-playwright
67- // This is needed because pnpm overrides don't affect Node.js module resolution at config load time
68- const viteConfigPath = join ( projectDir , 'vibe-dashboard' , 'apps' , 'dashboard' , 'vite.config.ts' ) ;
69- const viteConfigContent = fs
70- . readFileSync ( viteConfigPath , 'utf8' )
71- . replace ( 'from "@vitest/browser-playwright"' , 'from "vitest/browser-playwright"' ) ;
72- fs . writeFileSync ( viteConfigPath , viteConfigContent ) ;
73-
74- // Add pnpm overrides to ensure @vitest /* packages are installed at matching versions
75- const vitestVersion = vitestPackageJson . devDependencies [ '@vitest/runner' ] ;
76- const vitestOverrides = [
77- '@vitest/runner' ,
78- '@vitest/utils' ,
79- '@vitest/spy' ,
80- '@vitest/expect' ,
81- '@vitest/snapshot' ,
82- '@vitest/mocker' ,
83- '@vitest/pretty-format' ,
84- ] ;
85-
86- const pnpmWorkspaceContent = fs . readFileSync ( pnpmWorkspacePath , 'utf8' ) ;
87- if ( ! pnpmWorkspaceContent . includes ( '"@vitest/runner":' ) ) {
88- const overridesStr = vitestOverrides . map ( ( pkg ) => ` "${ pkg } ": "${ vitestVersion } "` ) . join ( '\n' ) ;
89- const updatedContent = pnpmWorkspaceContent . replace (
90- / ^ o v e r r i d e s : \n / m,
91- `overrides:\n${ overridesStr } \n` ,
92- ) ;
93- fs . writeFileSync ( pnpmWorkspacePath , updatedContent ) ;
94- }
95- }
96-
97- async function patchSkeleton ( ) {
98- const packageJsonPath = join ( projectDir , 'skeleton' , 'package.json' ) ;
99- const packageJson = JSON . parse ( fs . readFileSync ( packageJsonPath , 'utf8' ) ) ;
100-
101- // Change test command from "vitest run" to "vite test"
102- packageJson . scripts . test = 'vite test' ;
103-
104- // Add pnpm overrides with tgz files
105- // Include @vitest /browser and @vitest /browser-playwright to use bundled versions
106- packageJson . pnpm = packageJson . pnpm || { } ;
107- packageJson . pnpm . overrides = {
108- ...packageJson . pnpm . overrides ,
109- vite : `file:${ tgzPath } /voidzero-dev-vite-plus-core-0.0.0.tgz` ,
110- 'rolldown-vite' : `file:${ tgzPath } /voidzero-dev-vite-plus-core-0.0.0.tgz` ,
111- vitest : `file:${ tgzPath } /voidzero-dev-vite-plus-test-0.0.0.tgz` ,
112- '@vitest/browser' : `file:${ tgzPath } /voidzero-dev-vite-plus-test-0.0.0.tgz` ,
113- '@vitest/browser-playwright' : `file:${ tgzPath } /voidzero-dev-vite-plus-test-0.0.0.tgz` ,
114- '@voidzero-dev/vite-plus' : `file:${ tgzPath } /voidzero-dev-vite-plus-0.0.0.tgz` ,
115- '@voidzero-dev/vite-plus-core' : `file:${ tgzPath } /voidzero-dev-vite-plus-core-0.0.0.tgz` ,
116- '@voidzero-dev/vite-plus-test' : `file:${ tgzPath } /voidzero-dev-vite-plus-test-0.0.0.tgz` ,
117- } ;
118-
119- packageJson . devDependencies = {
120- ...packageJson . devDependencies ,
121- '@voidzero-dev/vite-plus' : `latest` ,
122- playwright : `catalog:` ,
123- } ;
124-
125- // Relax engine constraints to support broader node versions
126- if ( packageJson . engines ?. node ) {
127- packageJson . engines . node = '>=22.0.0' ;
128- }
129-
130- fs . writeFileSync ( packageJsonPath , JSON . stringify ( packageJson , null , 2 ) + '\n' ) ;
131-
132- const vitestVersion = vitestPackageJson . devDependencies [ '@vitest/expect' ] ;
133-
134- // Patch pnpm-workspace.yaml
135- const pnpmWorkspacePath = join ( projectDir , 'skeleton' , 'pnpm-workspace.yaml' ) ;
136- let pnpmWorkspaceContent = fs
137- . readFileSync ( pnpmWorkspacePath , 'utf8' )
138- . replace ( `trustPolicy: no-downgrade` , '\n' )
139- . replace (
140- / ' @ v i t e s t \/ b r o w s e r - p l a y w r i g h t ' : [ \d . ] + / ,
141- `'@vitest/browser-playwright': ${ vitestVersion } ` ,
142- ) ;
143-
144- // Add entries to existing minimumReleaseAgeExclude if it exists, otherwise append new section
145- const newExcludes = [ "'@voidzero-dev/*'" , "'@vitest/*'" , 'oxlint' , 'oxfmt' , 'oxlint-tsgolint' ] ;
146- if ( pnpmWorkspaceContent . includes ( 'minimumReleaseAgeExclude:' ) ) {
147- // Find the minimumReleaseAgeExclude section and add new entries
148- pnpmWorkspaceContent = pnpmWorkspaceContent . replace (
149- / m i n i m u m R e l e a s e A g e E x c l u d e : \n ( (?: - .+ \n ) + ) / ,
150- ( _ , existingEntries ) => {
151- const newEntriesStr = newExcludes . map ( ( e ) => ` - ${ e } \n` ) . join ( '' ) ;
152- return `minimumReleaseAgeExclude:\n${ existingEntries } ${ newEntriesStr } ` ;
153- } ,
154- ) ;
155- } else {
156- pnpmWorkspaceContent += `\nminimumReleaseAgeExclude:\n${ newExcludes . map ( ( e ) => ` - ${ e } ` ) . join ( '\n' ) } \n` ;
157- }
158-
159- // Add peerDependencyRules if not present
160- if ( ! pnpmWorkspaceContent . includes ( 'peerDependencyRules:' ) ) {
161- pnpmWorkspaceContent += `
162- peerDependencyRules:
163- allowAny:
164- - vite
165- - vitest
166- ` ;
167- }
168-
169- fs . writeFileSync ( pnpmWorkspacePath , pnpmWorkspaceContent ) ;
170-
171- // Update vite.config.ts files to import from vitest/browser-playwright instead of @vitest/browser-playwright
172- // This is needed because pnpm overrides don't affect Node.js module resolution at config load time
173- const skeletonReactConfigPath = join (
174- projectDir ,
175- 'skeleton' ,
176- 'packages' ,
177- 'skeleton-react' ,
178- 'vite.config.ts' ,
179- ) ;
180- const skeletonSvelteConfigPath = join (
181- projectDir ,
182- 'skeleton' ,
183- 'packages' ,
184- 'skeleton-svelte' ,
185- 'vite.config.ts' ,
186- ) ;
187-
188- for ( const configPath of [ skeletonReactConfigPath , skeletonSvelteConfigPath ] ) {
189- const content = fs
190- . readFileSync ( configPath , 'utf8' )
191- // Handle both single and double quotes
192- . replace ( / f r o m [ ' " ] @ v i t e s t \/ b r o w s e r - p l a y w r i g h t [ ' " ] / , 'from "vitest/browser-playwright"' ) ;
193- fs . writeFileSync ( configPath , content ) ;
194- }
195-
196- // Remove @vitest /browser-playwright from package devDependencies
197- // These are bundled in our vitest package now
198- const packagesToUpdate = [
199- join ( projectDir , 'skeleton' , 'packages' , 'skeleton-react' , 'package.json' ) ,
200- join ( projectDir , 'skeleton' , 'packages' , 'skeleton-svelte' , 'package.json' ) ,
201- ] ;
202-
203- for ( const pkgPath of packagesToUpdate ) {
204- const pkg = JSON . parse ( fs . readFileSync ( pkgPath , 'utf8' ) ) ;
205- if ( pkg . devDependencies ?. [ '@vitest/browser-playwright' ] ) {
206- delete pkg . devDependencies [ '@vitest/browser-playwright' ] ;
207- }
208- fs . writeFileSync ( pkgPath , JSON . stringify ( pkg , null , '\t' ) + '\n' ) ;
209- }
210- }
211-
21220async function migrateProject ( project : string ) {
21321 const repoRoot = join ( projectDir , project ) ;
21422 // run vite migrate
@@ -228,17 +36,4 @@ async function migrateProject(project: string) {
22836 } ) ;
22937}
23038
231- switch ( project ) {
232- case 'vibe-dashboard' :
233- await patchVibeDashboard ( ) ;
234- break ;
235- case 'skeleton' :
236- await patchSkeleton ( ) ;
237- break ;
238- case 'rollipop' :
239- await migrateProject ( project ) ;
240- break ;
241- default :
242- console . error ( `Project ${ project } is not supported` ) ;
243- process . exit ( 1 ) ;
244- }
39+ await migrateProject ( project ) ;
0 commit comments