import * as v from "valibot"; import "dotenv/config"; /** * Settings schema using Valibot for validation */ export const settingsSchema = v.object({ appName: v.string(), nodeEnv: v.string(), logLevel: v.string(), isDevelopment: v.optional(v.boolean()), redisUrl: v.string(), databaseUrl: v.string(), internalApiKey: v.string(), debugKey: v.string(), processorApiUrl: v.string(), betterAuthUrl: v.string(), betterAuthSecret: v.string(), twoFaSecret: v.string(), twofaSessionExpiryMinutes: v.optional(v.number()), twofaRequiredHours: v.optional(v.number()), defaultAdminEmail: v.string(), defaultAdminPassword: v.string(), otelServiceName: v.string(), otelExporterOtlpHttpEndpoint: v.string(), }); export type Settings = v.InferOutput; /** * Helper to get environment variable with default value */ function getEnv(key: string, defaultValue: string = ""): string { return process.env[key] ?? defaultValue; } /** * Helper to get environment variable as number with default value */ function getEnvNumber(key: string, defaultValue: number): number { const value = process.env[key]; if (!value) return defaultValue; const parsed = Number(value); return Number.isNaN(parsed) ? defaultValue : parsed; } /** * Load and validate settings from environment variables */ function loadSettings(): Settings { const nodeEnv = getEnv("NODE_ENV", "development"); const rawSettings = { appName: getEnv("APP_NAME", "App"), nodeEnv, logLevel: getEnv("LOG_LEVEL", "info"), isDevelopment: nodeEnv === "development", redisUrl: getEnv("REDIS_URL", "redis://localhost:6379"), databaseUrl: getEnv("DATABASE_URL"), internalApiKey: getEnv("INTERNAL_API_KEY"), debugKey: getEnv("DEBUG_KEY"), processorApiUrl: getEnv("PROCESSOR_API_URL", "http://localhost:3000"), betterAuthUrl: getEnv("BETTER_AUTH_URL"), betterAuthSecret: getEnv("BETTER_AUTH_SECRET"), twoFaSecret: getEnv("TWOFA_SECRET"), twofaSessionExpiryMinutes: getEnvNumber( "TWOFA_SESSION_EXPIRY_MINUTES", 10, ), twofaRequiredHours: getEnvNumber("TWOFA_REQUIRED_HOURS", 24), defaultAdminEmail: getEnv("DEFAULT_ADMIN_EMAIL"), defaultAdminPassword: getEnv("DEFAULT_ADMIN_PASSWORD"), otelServiceName: getEnv("OTEL_SERVICE_NAME"), otelExporterOtlpHttpEndpoint: getEnv( "OTEL_EXPORTER_OTLP_HTTP_ENDPOINT", ), }; try { return v.parse(settingsSchema, rawSettings); } catch (error) { console.error("❌ Settings validation failed:"); if (error instanceof v.ValiError) { for (const issue of error.issues) { console.error( ` - ${issue.path?.map((p: any) => p.key).join(".")}: ${issue.message}`, ); } } else { console.error(error); } throw new Error( "Failed to load settings. Check environment variables.", ); } } export const settings = loadSettings(); export const getSetting = (key: K): Settings[K] => { return settings[key]; }; console.log(`✅ Settings loaded | ${settings.appName} (${settings.nodeEnv})`);