SPB Git

spb/phi-conseil

Public
2.1 KB · 63 lines typescript
1import { z } from "zod";23/**4 * Variables d'environnement serveur, validées au premier accès.5 * Aucune n'est exposée au navigateur (pas de préfixe NEXT_PUBLIC_ sauf6 * NEXT_PUBLIC_SITE_URL et NEXT_PUBLIC_CONTENT_PREVIEW, non sensibles).7 */8const schema = z.object({9  NODE_ENV: z.enum(["development", "test", "production"]).default("development"),10  NEXT_PUBLIC_SITE_URL: z.url().optional(),11  NEXT_PUBLIC_CONTENT_PREVIEW: z.enum(["0", "1"]).default("0"),1213  /** `smtp` = envoi réel ; `log` = journalisation locale uniquement (dev/CI). */14  CONTACT_TRANSPORT: z.enum(["smtp", "log"]).default("log"),15  CONTACT_TO: z.email().optional(),16  CONTACT_FROM: z.email().optional(),17  SMTP_HOST: z.string().optional(),18  SMTP_PORT: z.coerce.number().int().positive().optional(),19  SMTP_SECURE: z20    .enum(["true", "false"])21    .default("false")22    .transform((v) => v === "true"),23  SMTP_USER: z.string().optional(),24  SMTP_PASS: z.string().optional(),2526  /** Limitation de débit du formulaire : N requêtes par fenêtre (secondes). */27  CONTACT_RATE_LIMIT: z.coerce.number().int().positive().default(5),28  CONTACT_RATE_WINDOW_S: z.coerce.number().int().positive().default(600),29});3031export type Env = z.infer<typeof schema>;3233let cached: Env | null = null;3435export function getEnv(): Env {36  if (cached) return cached;37  const parsed = schema.safeParse(process.env);38  if (!parsed.success) {39    const issues = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");40    throw new Error(`Variables d'environnement invalides : ${issues}`);41  }42  const env = parsed.data;43  if (env.CONTACT_TRANSPORT === "smtp") {44    const missing = (["CONTACT_TO", "CONTACT_FROM", "SMTP_HOST", "SMTP_PORT"] as const).filter(45      (k) => !env[k],46    );47    if (missing.length) {48      throw new Error(`CONTACT_TRANSPORT=smtp requiert : ${missing.join(", ")}`);49    }50  }51  cached = env;52  return env;53}5455/** Pour les tests : vider le cache après modification de process.env. */56export function resetEnvCache() {57  cached = null;58}5960export function siteUrl(fallback: string): string {61  return process.env.NEXT_PUBLIC_SITE_URL ?? fallback;62}63
Files · main
Menu

Theme