@@ -170,6 +170,134 @@ describe("transform mode plugin", () => {
170170 }
171171 } ) ;
172172
173+ it ( "fails during config resolution when the environment is invalid" , async ( ) => {
174+ const root = mkdtempSync ( join ( tmpdir ( ) , "arkenv-vite-invalid-startup-" ) ) ;
175+ temps . push ( root ) ;
176+ writeFileSync (
177+ join ( root , "env.ts" ) ,
178+ 'import arkenv from "@arkenv/core";\n\nexport const env = arkenv({ REQUIRED_TOKEN: "string" });\n' ,
179+ ) ;
180+ const plugin = arkenvPlugin ( ) as any ;
181+ const context = { } as any ;
182+
183+ if ( plugin . config && typeof plugin . config === "function" ) {
184+ plugin . config . call (
185+ context ,
186+ { root, envDir : root } ,
187+ { mode : "test" , command : "serve" } ,
188+ ) ;
189+ }
190+
191+ await expect (
192+ Promise . resolve ( ) . then ( ( ) =>
193+ plugin . configResolved ?. call ( context , {
194+ root,
195+ envDir : root ,
196+ envPrefix : "VITE_" ,
197+ } as any ) ,
198+ ) ,
199+ ) . rejects . toMatchObject ( { name : "ArkEnvError" } ) ;
200+ expect ( process . env . REQUIRED_TOKEN ) . toBeUndefined ( ) ;
201+ } ) ;
202+
203+ it ( "revalidates valid schema and dotenv changes during HMR" , async ( ) => {
204+ const root = mkdtempSync ( join ( tmpdir ( ) , "arkenv-vite-hmr-" ) ) ;
205+ temps . push ( root ) ;
206+ const schemaPath = join ( root , "env.ts" ) ;
207+ const dotenvPath = join ( root , ".env.test" ) ;
208+ writeFileSync (
209+ schemaPath ,
210+ 'import arkenv from "@arkenv/core";\n\nexport const env = arkenv({ VITE_API_URL: "string" });\n' ,
211+ ) ;
212+ writeFileSync ( dotenvPath , "VITE_API_URL=https://example.com\n" ) ;
213+ const plugin = arkenvPlugin ( { schemaPath } ) as any ;
214+ const server = {
215+ moduleGraph : {
216+ getModulesByFile : ( ) => new Set ( [ { id : schemaPath } ] ) ,
217+ invalidateModule : ( ) => { } ,
218+ } ,
219+ } as any ;
220+ const context = { } as any ;
221+
222+ plugin . config ?. call (
223+ context ,
224+ { root, envDir : root } ,
225+ { mode : "test" , command : "serve" } ,
226+ ) ;
227+ await plugin . configResolved ?. call ( context , {
228+ root,
229+ envDir : root ,
230+ envPrefix : "VITE_" ,
231+ } as any ) ;
232+
233+ const schemaUpdate = plugin . handleHotUpdate ?. call ( context , {
234+ file : schemaPath ,
235+ server,
236+ } as any ) ;
237+ expect ( schemaUpdate ) . toHaveLength ( 1 ) ;
238+ writeFileSync ( dotenvPath , "VITE_API_URL=https://updated.example.com\n" ) ;
239+ const dotenvUpdate = plugin . handleHotUpdate ?. call ( context , {
240+ file : dotenvPath ,
241+ server,
242+ } as any ) ;
243+ expect ( dotenvUpdate ) . toHaveLength ( 1 ) ;
244+
245+ const clientModule = await plugin . transform ?. call (
246+ {
247+ environment : {
248+ name : "client" ,
249+ config : { consumer : "client" } ,
250+ } ,
251+ } ,
252+ "export const env = {}" ,
253+ schemaPath ,
254+ ) ;
255+ expect ( clientModule ?. code ) . toContain (
256+ '"VITE_API_URL": "https://updated.example.com"' ,
257+ ) ;
258+ } ) ;
259+
260+ it ( "propagates invalid dotenv values during HMR" , async ( ) => {
261+ const root = mkdtempSync ( join ( tmpdir ( ) , "arkenv-vite-invalid-hmr-" ) ) ;
262+ temps . push ( root ) ;
263+ const schemaPath = join ( root , "env.ts" ) ;
264+ const dotenvPath = join ( root , ".env.test" ) ;
265+ writeFileSync (
266+ schemaPath ,
267+ 'import arkenv from "@arkenv/core";\n\nexport const env = arkenv({ VITE_PORT: "number" });\n' ,
268+ ) ;
269+ writeFileSync ( dotenvPath , "VITE_PORT=8080\n" ) ;
270+ const plugin = arkenvPlugin ( { schemaPath } ) as any ;
271+ const server = {
272+ moduleGraph : {
273+ getModulesByFile : ( ) => new Set ( ) ,
274+ invalidateModule : ( ) => { } ,
275+ } ,
276+ } as any ;
277+ const context = { } as any ;
278+
279+ plugin . config ?. call (
280+ context ,
281+ { root, envDir : root } ,
282+ { mode : "test" , command : "serve" } ,
283+ ) ;
284+ await plugin . configResolved ?. call ( context , {
285+ root,
286+ envDir : root ,
287+ envPrefix : "VITE_" ,
288+ } as any ) ;
289+ writeFileSync ( dotenvPath , "VITE_PORT=not-a-number\n" ) ;
290+
291+ await expect (
292+ Promise . resolve ( ) . then ( ( ) =>
293+ plugin . handleHotUpdate ?. call ( context , {
294+ file : dotenvPath ,
295+ server,
296+ } as any ) ,
297+ ) ,
298+ ) . rejects . toMatchObject ( { name : "ArkEnvError" } ) ;
299+ } ) ;
300+
173301 it ( "passes through the env module unchanged in the SSR graph" , async ( ) => {
174302 const fixtureDir = join ( __dirname , "__fixtures__" , "transform-env" ) ;
175303 const plugin = arkenvPlugin ( { schemaPath : join ( fixtureDir , "env.ts" ) } ) ;
0 commit comments