import { z } from "zod"; const booleanStringSchema = z .string() .trim() .transform((value) => value.toLowerCase()) .pipe(z.enum(["true", "false", "1", "0", "yes", "no"])) .transform((value) => ["true", "1", "yes"].includes(value)); const serverConfigSchema = z.object({ DATABASE_URL: z.string().url(), AUTH_SECRET: z.string().min(1), AUTH_GOOGLE_ID: z.string().min(1), AUTH_GOOGLE_SECRET: z.string().min(1), ADMIN_EMAILS: z .string() .min(1) .transform((value) => value .split(",") .map((email) => email.trim().toLowerCase()) .filter(Boolean), ), APP_URL: z.string().url(), RSVP_DEADLINE: z.iso.date(), S3_ENDPOINT: z.string().url(), S3_REGION: z.string().min(1), S3_BUCKET: z.string().min(1), S3_ACCESS_KEY_ID: z.string().min(1), S3_SECRET_ACCESS_KEY: z.string().min(1), S3_FORCE_PATH_STYLE: booleanStringSchema.default(true), }); export type ServerConfig = z.infer; const buildTimeConfigDefaults = { DATABASE_URL: "postgres://wedding:wedding@wedding-db:5432/wedding", AUTH_SECRET: "docker-build-placeholder", AUTH_GOOGLE_ID: "docker-build-placeholder", AUTH_GOOGLE_SECRET: "docker-build-placeholder", ADMIN_EMAILS: "admin@example.com", APP_URL: "https://wedding.example.com", RSVP_DEADLINE: "2099-12-31", S3_ENDPOINT: "http://wedding-minio:9000", S3_REGION: "us-east-1", S3_BUCKET: "wedding-uploads", S3_ACCESS_KEY_ID: "minioadmin", S3_SECRET_ACCESS_KEY: "minioadmin", S3_FORCE_PATH_STYLE: "true", }; export function getServerConfig(env: NodeJS.ProcessEnv = process.env) { if (env.SKIP_ENV_VALIDATION === "1") { return serverConfigSchema.parse({ ...buildTimeConfigDefaults, ...env }); } return serverConfigSchema.parse(env); } export function getDatabaseUrl(env: NodeJS.ProcessEnv = process.env) { if (env.SKIP_ENV_VALIDATION === "1") { return buildTimeConfigDefaults.DATABASE_URL; } return z.string().url().parse(env.DATABASE_URL); }