1+ import { readFileSync } from "node:fs" ;
12import { writeFile } from "node:fs/promises" ;
23import { beforeEach , describe , it } from "vitest" ;
34import {
@@ -17,7 +18,26 @@ describe("vite-config utils", () => {
1718 } ) ;
1819
1920 describe ( "checkIfViteConfigUsesCloudflarePlugin" , ( ) => {
20- it ( "should handle vite config with function-based defineConfig" , async ( {
21+ it ( "should detect cloudflare plugin in function-based defineConfig" , async ( {
22+ expect,
23+ } ) => {
24+ await writeFile (
25+ "vite.config.ts" ,
26+ `
27+ import { defineConfig } from 'vite';
28+ import { cloudflare } from '@cloudflare/vite-plugin';
29+
30+ export default defineConfig(() => ({
31+ plugins: [cloudflare()]
32+ }));
33+ `
34+ ) ;
35+
36+ const result = checkIfViteConfigUsesCloudflarePlugin ( "." ) ;
37+ expect ( result ) . toBe ( true ) ;
38+ } ) ;
39+
40+ it ( "should return false for function-based defineConfig without cloudflare plugin" , async ( {
2141 expect,
2242 } ) => {
2343 await writeFile (
@@ -33,7 +53,6 @@ export default defineConfig(() => ({
3353
3454 const result = checkIfViteConfigUsesCloudflarePlugin ( "." ) ;
3555 expect ( result ) . toBe ( false ) ;
36- expect ( std . debug ) . toContain ( "Vite config uses a non-object expression" ) ;
3756 } ) ;
3857
3958 it ( "should handle vite config without plugins array" , async ( {
@@ -76,7 +95,7 @@ export default defineConfig({
7695 } ) ;
7796
7897 describe ( "transformViteConfig" , ( ) => {
79- it ( "should throw UserError for function-based defineConfig" , async ( {
98+ it ( "should successfully transform function-based defineConfig with arrow expression body " , async ( {
8099 expect,
81100 } ) => {
82101 await writeFile (
@@ -90,9 +109,142 @@ export default defineConfig(() => ({
90109`
91110 ) ;
92111
93- expect ( ( ) => transformViteConfig ( "." ) ) . toThrowError (
94- / C a n n o t m o d i f y V i t e c o n f i g : e x p e c t e d a n o b j e c t l i t e r a l /
112+ expect ( ( ) => transformViteConfig ( "." ) ) . not . toThrow ( ) ;
113+ const result = readFileSync ( "vite.config.ts" , "utf-8" ) ;
114+ expect ( result ) . toContain (
115+ 'import { cloudflare } from "@cloudflare/vite-plugin"'
116+ ) ;
117+ expect ( result ) . toContain ( "cloudflare()" ) ;
118+ } ) ;
119+
120+ it ( "should successfully transform function-based defineConfig with destructured params" , async ( {
121+ expect,
122+ } ) => {
123+ // This is the exact pattern from the React Router node-postgres template
124+ await writeFile (
125+ "vite.config.ts" ,
126+ `
127+ import { reactRouter } from "@react-router/dev/vite";
128+ import tailwindcss from "@tailwindcss/vite";
129+ import { defineConfig } from "vite";
130+ import tsconfigPaths from "vite-tsconfig-paths";
131+
132+ export default defineConfig(({ isSsrBuild }) => ({
133+ build: {
134+ rollupOptions: isSsrBuild
135+ ? {
136+ input: "./server/app.ts",
137+ }
138+ : undefined,
139+ },
140+ plugins: [tailwindcss(), reactRouter(), tsconfigPaths()],
141+ }));
142+ `
143+ ) ;
144+
145+ expect ( ( ) => transformViteConfig ( "." ) ) . not . toThrow ( ) ;
146+ const result = readFileSync ( "vite.config.ts" , "utf-8" ) ;
147+ expect ( result ) . toContain (
148+ 'import { cloudflare } from "@cloudflare/vite-plugin"'
149+ ) ;
150+ expect ( result ) . toContain ( "cloudflare()" ) ;
151+ // The existing plugins should be preserved
152+ expect ( result ) . toContain ( "tailwindcss()" ) ;
153+ expect ( result ) . toContain ( "reactRouter()" ) ;
154+ expect ( result ) . toContain ( "tsconfigPaths()" ) ;
155+ // The function structure should be preserved
156+ expect ( result ) . toContain ( "isSsrBuild" ) ;
157+ } ) ;
158+
159+ it ( "should successfully transform function-based defineConfig with block body" , async ( {
160+ expect,
161+ } ) => {
162+ await writeFile (
163+ "vite.config.ts" ,
164+ `
165+ import { defineConfig } from 'vite';
166+
167+ export default defineConfig(() => {
168+ return {
169+ plugins: []
170+ };
171+ });
172+ `
173+ ) ;
174+
175+ expect ( ( ) => transformViteConfig ( "." ) ) . not . toThrow ( ) ;
176+ const result = readFileSync ( "vite.config.ts" , "utf-8" ) ;
177+ expect ( result ) . toContain (
178+ 'import { cloudflare } from "@cloudflare/vite-plugin"'
179+ ) ;
180+ expect ( result ) . toContain ( "cloudflare()" ) ;
181+ } ) ;
182+
183+ it ( "should successfully transform function expression defineConfig" , async ( {
184+ expect,
185+ } ) => {
186+ await writeFile (
187+ "vite.config.ts" ,
188+ `
189+ import { defineConfig } from 'vite';
190+
191+ export default defineConfig(function() {
192+ return {
193+ plugins: []
194+ };
195+ });
196+ `
197+ ) ;
198+
199+ expect ( ( ) => transformViteConfig ( "." ) ) . not . toThrow ( ) ;
200+ const result = readFileSync ( "vite.config.ts" , "utf-8" ) ;
201+ expect ( result ) . toContain (
202+ 'import { cloudflare } from "@cloudflare/vite-plugin"'
203+ ) ;
204+ expect ( result ) . toContain ( "cloudflare()" ) ;
205+ } ) ;
206+
207+ it ( "should pass viteEnvironmentName option with function-based config" , async ( {
208+ expect,
209+ } ) => {
210+ await writeFile (
211+ "vite.config.ts" ,
212+ `
213+ import { defineConfig } from 'vite';
214+
215+ export default defineConfig(() => ({
216+ plugins: []
217+ }));
218+ `
219+ ) ;
220+
221+ expect ( ( ) =>
222+ transformViteConfig ( "." , { viteEnvironmentName : "ssr" } )
223+ ) . not . toThrow ( ) ;
224+ const result = readFileSync ( "vite.config.ts" , "utf-8" ) ;
225+ expect ( result ) . toContain ( "viteEnvironment" ) ;
226+ expect ( result ) . toContain ( '"ssr"' ) ;
227+ } ) ;
228+
229+ it ( "should remove incompatible plugins from function-based config" , async ( {
230+ expect,
231+ } ) => {
232+ await writeFile (
233+ "vite.config.ts" ,
234+ `
235+ import { defineConfig } from 'vite';
236+
237+ export default defineConfig(() => ({
238+ plugins: [nitro(), someOther()]
239+ }));
240+ `
95241 ) ;
242+
243+ expect ( ( ) => transformViteConfig ( "." ) ) . not . toThrow ( ) ;
244+ const result = readFileSync ( "vite.config.ts" , "utf-8" ) ;
245+ expect ( result ) . not . toContain ( "nitro()" ) ;
246+ expect ( result ) . toContain ( "someOther()" ) ;
247+ expect ( result ) . toContain ( "cloudflare()" ) ;
96248 } ) ;
97249
98250 it ( "should throw UserError when plugins array is missing" , async ( {
@@ -114,6 +266,25 @@ export default defineConfig({
114266 ) ;
115267 } ) ;
116268
269+ it ( "should throw UserError when plugins array is missing in function-based config" , async ( {
270+ expect,
271+ } ) => {
272+ await writeFile (
273+ "vite.config.ts" ,
274+ `
275+ import { defineConfig } from 'vite';
276+
277+ export default defineConfig(() => ({
278+ server: { port: 3000 }
279+ }));
280+ `
281+ ) ;
282+
283+ expect ( ( ) => transformViteConfig ( "." ) ) . toThrowError (
284+ / C a n n o t m o d i f y V i t e c o n f i g : c o u l d n o t f i n d a v a l i d p l u g i n s a r r a y /
285+ ) ;
286+ } ) ;
287+
117288 it ( "should successfully transform valid vite config" , async ( {
118289 expect,
119290 } ) => {
0 commit comments