1- import { z , ZodError , ZodIntersection , ZodTypeAny } from "zod" ;
1+ import { z , ZodError } from "zod" ;
22
3- const commonSchema = z . object ( {
4- NODE_ENV : z . enum ( [ "local" , "test" , "production" ] ) . default ( "local" ) ,
5-
6- // Server & auth
7- SERVER_HOST : z . string ( ) . default ( "localhost" ) ,
8- SERVER_PORT : z . coerce . number ( ) . positive ( ) . default ( 8888 ) ,
9- FRONTEND_URL : z . string ( ) . default ( "http://localhost:5173" ) , // for CORS in production
10- COOKIE_SECRET : z . string ( ) . min ( 32 ) . default ( "secret-cookie-mininum-32-chars-long" ) , // protect from xss
11- SESSION_TTL : z . number ( ) . default ( 60 * 60 * 24 ) , // 24 hours in seconds
12-
13- // LLM (TODO: update to use LM Studio)
14- DEEPINFRA_MODEL_URL : z . string ( ) . default ( "https://api.deepinfra.com/v1/inference/Qwen/QwQ-32B" ) ,
15- DEEPINFRA_API_KEY : z . string ( ) ,
16-
17- // Cache
18- DRAGONFLY_PORT : z . coerce . number ( ) . positive ( ) . default ( 6379 ) ,
19- DEFAULT_CACHE_TIME : z . coerce
20- . number ( )
21- . positive ( )
22- . default ( 60 * 60 * 24 ) , // 24 hours in seconds
23-
24- // API keys
25- MAINNET_RPC_URL : z . string ( ) . default ( "https://eth.llamarpc.com" ) ,
26- MAINNET_ETHERSCAN_API_KEY : z . string ( ) . default ( "" ) ,
27- MAINNET_BLOCKSCOUT_API_KEY : z . string ( ) . default ( "" ) ,
28- } ) ;
29-
30- /**
31- * Parses environment variables without validation or process exit Useful for client-side code that needs env defaults
32- * but not validation
33- */
34- export function parseEnv < TSchema extends ZodTypeAny | undefined = undefined > (
35- schema ?: TSchema ,
36- env : Record < string , unknown > = { } ,
37- ) : z . infer < TSchema extends ZodTypeAny ? ZodIntersection < typeof commonSchema , TSchema > : typeof commonSchema > {
38- const envSchema = schema !== undefined ? z . intersection ( commonSchema , schema ) : commonSchema ;
39- try {
40- return envSchema . safeParse ( env ) ;
41- } catch ( error ) {
42- // Return defaults for any missing values
43- return envSchema . parse ( { } ) ;
44- }
45- }
3+ import { ServerEnv , serverEnvSchema } from "./env.server" ;
4+ import { SharedEnv , sharedEnvSchema } from "./env.shared" ;
5+ import { WebEnv , webEnvSchema } from "./env.web" ;
466
477/**
488 * Validates environment variables and exits process if invalid Used by server-side code that requires proper env
499 * configuration
5010 */
51- export function validateEnv < TSchema extends ZodTypeAny | undefined = undefined > (
52- schema ?: TSchema ,
53- ) : z . infer < TSchema extends ZodTypeAny ? ZodIntersection < typeof commonSchema , TSchema > : typeof commonSchema > {
54- const envSchema = schema !== undefined ? z . intersection ( commonSchema , schema ) : commonSchema ;
11+ export function parseEnv < T extends "web" | "server" = "server" > (
12+ type ?: T ,
13+ ) : T extends "web" ? SharedEnv & WebEnv : SharedEnv & ServerEnv {
14+ const envSchema =
15+ type === "web" ? z . intersection ( sharedEnvSchema , webEnvSchema ) : z . intersection ( sharedEnvSchema , serverEnvSchema ) ;
16+
5517 try {
56- return envSchema . parse ( process . env ) ;
18+ // @ts -expect-error Property env doesn't exist in import.meta
19+ const envSource = type === "web" ? import . meta. env : process . env ;
20+ return envSchema . parse ( envSource ) as any ;
5721 } catch ( error ) {
5822 if ( error instanceof ZodError ) {
5923 // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -64,3 +28,8 @@ export function validateEnv<TSchema extends ZodTypeAny | undefined = undefined>(
6428 throw error ;
6529 }
6630}
31+
32+ // Export types for convenience
33+ export type { SharedEnv } from "./env.shared" ;
34+ export type { WebEnv , WebEnvironment } from "./env.web" ;
35+ export type { ServerEnv , ServerEnvironment } from "./env.server" ;
0 commit comments