import { z } from "zod"; // Server-side environment schema (t3.gg style) const serverSchema = z.object({ // Full MySQL connection URL, e.g. mysql://user:pass@host:3306/zxdb ZXDB_URL: z .string() .url() .refine((s) => s.startsWith("mysql://"), { message: "ZXDB_URL must be a valid mysql:// URL", }), // Optional file prefixes for ZXDB and WOS ZXDB_FILE_PREFIX: z.string().optional(), WOS_FILE_PREFIX: z.string().optional(), // Local file paths for mirroring ZXDB_LOCAL_FILEPATH: z.string().optional(), WOS_LOCAL_FILEPATH: z.string().optional(), // OIDC Configuration OIDC_PROVIDER_URL: z.string().url().optional(), OIDC_CLIENT_ID: z.string().optional(), OIDC_CLIENT_SECRET: z.string().optional(), // Redis cache and SMTP mail URLs CACHE_URL: z.string().url().optional(), MAIL_URL: z.string().url().optional(), // System hostname for permalinks (mandatory) HOSTNAME: z.string().min(1), PROTO: z.string().startsWith("http"), }); function formatErrors(errors: z.ZodFormattedError, string>) { return Object.entries(errors) .map(([name, value]) => { if (value && "_errors" in value) { const errs = (value as z.ZodFormattedError)._errors; return `${name}: ${errs.join(", ")}`; } return `${name}: invalid`; }) .join("\n"); } const parsed = serverSchema.safeParse(process.env); if (!parsed.success) { // Fail fast with helpful output in server context console.error("❌ Invalid environment variables:\n" + formatErrors(parsed.error.format())); throw new Error("Invalid environment variables"); } export const env = parsed.data;