import { type LevelName, LogLevels, } from "https://deno.land/std@0.159.0/log/mod.ts"; export interface LogConfig { consoleLevelName: LevelName; } export interface PostgresConfig { url: string; poolSize: number; } export interface MailgunConfig { apiKey?: string; domain?: string; } export interface Config { log: LogConfig; postgres: PostgresConfig; mailgun: MailgunConfig; isDevelopmentMode: boolean; } function truthyEnv(key: string): boolean { return (Deno.env.get(key) || "").toString().toLowerCase().trim() in ["true", "1"]; } function toLogLevelName(s: string): LevelName | undefined { if (s in LogLevels) { return s as LevelName; } else { return undefined; } } export let config: Readonly; type Logger = { warning: (s: string, ...opts: unknown[]) => void }; export function setAll(newConfig: Config) { config = newConfig; } export function reload(): [ Config, ((logger: Logger) => void)[], ] { // since we want configuration to be setup before any logging, lets save logs here until the logger is setup const logCalls: ((logger: Logger) => void)[] = []; const envOrWarn = (key: string, fallback: string): string => { const val = Deno.env.get(key); if (!val) { logCalls.push((logger: Logger) => logger.warning(`${key} is not set! Using fallback: ${fallback}`) ); } return val || fallback; }; const envToIntOrWarn = (key: string, fallback: number): number => { const ev = envOrWarn(key, fallback.toString()); let result = parseInt(ev); if (isNaN(result)) { logCalls.push((logger: Logger) => logger.warning( `Specified ${key} '${ev}' is not a valid integer. Falling back to ${fallback}.`, ) ); result = fallback; } return result; }; const envToEnumOrWarn = ( key: string, converter: (s: string) => T | undefined, fallback: T, ): T => { const ev = envOrWarn(key, `${fallback}`); const result = converter(ev); if (result) { return result; } else { logCalls.push((logger: Logger) => logger.warning( `Specified ${key} '${ev}' is invalid. Falling back to ${fallback}`, ) ); return fallback; } }; const config: Config = { log: { consoleLevelName: envToEnumOrWarn("LOG_LEVEL", toLogLevelName, "INFO"), }, postgres: { url: envOrWarn( "POSTGRES_URL", "postgresql://postgres:@127.0.0.1:5432/lyricscreen", ), poolSize: envToIntOrWarn("POSTGRES_POOL_SIZE", 3), }, mailgun: {}, isDevelopmentMode: truthyEnv("DEVELOPMENT_MODE"), }; return [config, logCalls]; }