diff --git a/waspc/data/Generator/templates/react-app/plugins/validateEnv.ts b/waspc/data/Generator/templates/react-app/plugins/validateEnv.ts index 6c13d96c48..092b123b8c 100644 --- a/waspc/data/Generator/templates/react-app/plugins/validateEnv.ts +++ b/waspc/data/Generator/templates/react-app/plugins/validateEnv.ts @@ -1,14 +1,46 @@ import { type Plugin, loadEnv } from "vite"; -import { ensureEnvSchema } from 'wasp/env' +import { getValidatedDataOrError, type SchemaParsingResult } from 'wasp/env' import { clientEnvSchema } from 'wasp/client/env/schema' +const RED_COLOR = '\x1b[31m' + export function validateEnv(): Plugin { + let _validationResult: SchemaParsingResult = null return { name: 'wasp-validate-env', - config: (config) => { + configResolved: (config) => { const env = loadEnv(config.mode, process.cwd(), config.envPrefix) - ensureEnvSchema(env, clientEnvSchema) + + _validationResult = getValidatedDataOrError(env, clientEnvSchema) + + if (_validationResult.type !== 'error') { + return; + } + + if (config.command !== 'build') { + return; + } + + console.error(`${RED_COLOR}${_validationResult.message}`) + // Exit early if we are in build mode, because we can't show the error in the browser. + process.exit(1) }, + configureServer: (server) => { + if (_validationResult.type !== 'error') { + return; + } + + // Send the error to the browser. + server.ws.on('connection', (ws) => { + server.ws.send({ + type: 'error', + err: { + message: _validationResult.message, + stack: "" + } + }) + }) + } }; } diff --git a/waspc/data/Generator/templates/sdk/wasp/env/index.ts b/waspc/data/Generator/templates/sdk/wasp/env/index.ts index 36baddead2..35e3dda037 100644 --- a/waspc/data/Generator/templates/sdk/wasp/env/index.ts +++ b/waspc/data/Generator/templates/sdk/wasp/env/index.ts @@ -7,8 +7,38 @@ export function ensureEnvSchema( data: unknown, schema: Schema ): z.infer { + const result = getValidatedDataOrError(data, schema) + switch (result.type) { + case 'error': + console.error(`${redColor}${result.message}`) + throw new Error('Error parsing environment variables') + case 'success': + return result.data + default: + result satisfies never; + } +} + +// PRIVATE API (Vite config) +export type SchemaParsingResult = { + type: 'error', + message: string, +} | { + type: 'success', + data: Data, +} + +// PRIVATE API (SDK, Vite config) +export function getValidatedDataOrError( + data: unknown, + schema: Schema +): SchemaParsingResult> { try { - return schema.parse(data) + const validatedData = schema.parse(data) + return { + type: 'success', + data: validatedData, + } } catch (e) { if (e instanceof z.ZodError) { const errorOutput = [ @@ -21,10 +51,15 @@ export function ensureEnvSchema( } errorOutput.push('|') errorOutput.push('|════════════════════════════════') - console.error(redColor, errorOutput.join('\n')) - throw new Error('Error parsing environment variables') + return { + type: 'error', + message: errorOutput.join('\n'), + } } else { - throw e + return { + type: 'error', + message: e.message, + } } } -} +} \ No newline at end of file