import { z } from 'zod'; const envSchema = z.object({ NODE_ENV: z.enum(['development', 'test', 'production']).default('development'), PORT: z.coerce.number().min(1).max(65535).default(3000), HOST: z.string().default('0.0.0.0'), DATABASE_URL: z.string().min(1), REDIS_URL: z.string().min(1).default('redis://localhost:6379'), JWT_SECRET: z.string().min(32), JWT_ACCESS_TTL: z.string().default('15m'), JWT_REFRESH_TTL: z.string().default('7d'), LLM_BASE_URL: z.string().url().default('http://localhost:11434/v1'), LLM_MODEL: z.string().default('qwen2.5:14b'), LLM_FALLBACK_MODEL: z.string().optional(), LLM_API_KEY: z.string().optional(), LLM_TIMEOUT_MS: z.coerce.number().default(15000), LLM_MAX_RETRIES: z.coerce.number().min(0).default(1), LLM_RETRY_DELAY_MS: z.coerce.number().min(0).default(1000), LLM_TEMPERATURE: z.coerce.number().min(0).max(2).default(0.7), LLM_MAX_TOKENS: z.coerce.number().default(2048), RATE_LIMIT_LOGIN: z.coerce.number().default(5), RATE_LIMIT_REGISTER: z.coerce.number().default(3), RATE_LIMIT_FORGOT_PASSWORD: z.coerce.number().default(3), RATE_LIMIT_VERIFY_EMAIL: z.coerce.number().default(5), RATE_LIMIT_API_AUTHED: z.coerce.number().default(100), RATE_LIMIT_API_GUEST: z.coerce.number().default(30), CORS_ORIGINS: z.string().default('http://localhost:5173'), SENTRY_DSN: z.string().optional(), }); export type Env = z.infer; function parseEnv(): Env { const result = envSchema.safeParse(process.env); if (!result.success) { const msg = result.error.flatten().fieldErrors; throw new Error(`Invalid environment: ${JSON.stringify(msg)}`); } return result.data; } export const env = parseEnv(); export function getCorsOrigins(): string[] { return env.CORS_ORIGINS.split(',').map((s) => s.trim()).filter(Boolean); }