/** * This module contains utility functions to get environment variables with default values and validation. */ const normalizeValue = (value?: string | null): string | undefined => { if (value === undefined || value === null) { return undefined; } const trimmed = value.trim(); if (!trimmed) { return undefined; } const lowered = trimmed.toLowerCase(); if (lowered === "undefined" || lowered === "null") { return undefined; } return trimmed; }; const warnInvalid = (key: string, rawValue: string | undefined, reason: string) => { const received = rawValue !== undefined ? `; received "${rawValue}"` : ""; console.warn(`[config] ${key} ${reason}${received}`); // eslint-disable-line no-console }; export const getEnvString = (key: string, defaultValue = ""): string => { const normalized = normalizeValue(process.env[key]); return normalized ?? defaultValue; }; export const getEnvNumber = ( key: string, defaultValue: number ): number => { const normalized = normalizeValue(process.env[key]); if (normalized === undefined) { return defaultValue; } const parsed = Number.parseInt(normalized, 10); if (Number.isNaN(parsed)) { warnInvalid(key, normalized, `is not a valid number for key ${key}; falling back to default ${defaultValue}`); return defaultValue; } return parsed; }; /** * Like {@link getEnvNumber} but preserves fractional values (parseFloat, not parseInt). * Use for ratio/fraction settings such as RECONCILE_MAX_DELETE_FRACTION. */ export const getEnvFloat = ( key: string, defaultValue: number ): number => { const normalized = normalizeValue(process.env[key]); if (normalized === undefined) { return defaultValue; } const parsed = Number.parseFloat(normalized); if (Number.isNaN(parsed)) { warnInvalid(key, normalized, `is not a valid number for key ${key}; falling back to default ${defaultValue}`); return defaultValue; } return parsed; }; export const getEnvBoolean = (key: string, defaultValue = false): boolean => { const normalized = normalizeValue(process.env[key]); if (normalized === undefined) { return defaultValue; } const truthyValues = new Set(["true", "1", "yes", "y", "on"]); const falsyValues = new Set(["false", "0", "no", "n", "off"]); const lowered = normalized.toLowerCase(); if (truthyValues.has(lowered)) { return true; } if (falsyValues.has(lowered)) { return false; } warnInvalid(key, normalized, "is not a recognized boolean; falling back to default"); return defaultValue; }; export const getOptionalEnv = (key: string): string | undefined => { return normalizeValue(process.env[key]); };