import path from "node:path"; import { fileURLToPath } from "node:url"; import { config as loadEnv } from "dotenv"; import { z } from "zod"; // Load .env from the repo root when running outside Docker (no-op in containers). const __dirname = path.dirname(fileURLToPath(import.meta.url)); loadEnv({ path: path.resolve(__dirname, "../../../.env") }); loadEnv(); const bool = (def: boolean) => z .string() .optional() .transform((v) => (v === undefined ? def : v === "true" || v === "1")); const schema = z.object({ NODE_ENV: z.enum(["development", "production", "test"]).default("development"), PORT: z.coerce.number().default(3000), APP_URL: z.string().default("http://localhost:3000"), CORS_ORIGINS: z.string().optional().default(""), SESSION_SECRET: z.string().min(16).default("dev-secret-change-me-please-32chars-min"), SESSION_TTL_DAYS: z.coerce.number().default(30), DATABASE_URL: z.string().default("postgres://adc:adc@localhost:5432/adc"), REDIS_URL: z.string().default("redis://localhost:6379"), MINIO_ENDPOINT: z.string().default("localhost"), MINIO_PORT: z.coerce.number().default(9000), MINIO_SSL: bool(false), MINIO_ACCESS_KEY: z.string().default("minioadmin"), MINIO_SECRET_KEY: z.string().default("minioadmin"), MINIO_BUCKET: z.string().default("adc-retivo"), MINIO_PUBLIC_URL: z.string().optional().default(""), MB_USER_AGENT: z .string() .default("ADCRetivo/1.0 ( https://example.com contact:admin@example.com )"), ACOUSTID_API_KEY: z.string().optional().default(""), FPCALC_PATH: z.string().default("fpcalc"), ADMIN_EMAIL: z.string().default("admin@adc.retivo"), ADMIN_USERNAME: z.string().default("admin"), ADMIN_PASSWORD: z.string().default("admin123"), SERVE_WEB_DIST: z.string().optional().default(""), }); export const env = schema.parse(process.env); export const isProd = env.NODE_ENV === "production"; export const corsOrigins = env.CORS_ORIGINS.split(",") .map((s) => s.trim()) .filter(Boolean);