import { resolve } from "node:path"; export interface Config { host: string; port: number; storageDir: string; maxFileSize: number; fileTtlMs: number; rateLimitEnabled: boolean; rateLimitMax: number; rateLimitWindowMs: number; trustProxy: boolean; } const DEFAULT_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 1 week const SIZE_UNITS: Record = { B: 1, K: 1 << 10, KB: 1 << 10, KIB: 1 << 10, M: 1 << 20, MB: 1 << 20, MIB: 1 << 20, G: 1 << 30, GB: 1 << 30, GIB: 1 << 30, T: 1 << 40, TB: 1 << 40, TIB: 1 << 40, }; export function parseSize(value: string): number { const match = /^\s*(\d+(?:\.\d+)?)\s*([A-Za-z]*)\s*$/.exec(value); if (!match) throw new Error(`Invalid size value: "${value}"`); const num = parseFloat(match[1]!); const unit = (match[2] || "B").toUpperCase(); const factor = SIZE_UNITS[unit]; if (factor === undefined) throw new Error(`Invalid size unit in: "${value}"`); return Math.floor(num * factor); } function boolFromEnv(value: string | undefined, fallback: boolean): boolean { if (value === undefined) return fallback; return !["0", "false", "no", "off"].includes(value.trim().toLowerCase()); } export function loadConfig(env: Record = process.env): Config { const port = Number(env.PORT ?? "3000"); if (!Number.isInteger(port) || port < 1 || port > 65535) { throw new Error(`Invalid PORT: ${env.PORT}`); } const host = env.HOST ?? "0.0.0.0"; const storageDir = resolve(env.STORAGE_DIR ?? "./storage"); const maxFileSize = parseSize(env.MAX_FILE_SIZE ?? "10GB"); if (maxFileSize < 1024) throw new Error("MAX_FILE_SIZE must be at least 1KB"); const fileTtlMs = Number(env.FILE_TTL_MS ?? String(DEFAULT_TTL_MS)); if (!Number.isInteger(fileTtlMs) || fileTtlMs < 1) { throw new Error(`Invalid FILE_TTL_MS: ${env.FILE_TTL_MS}`); } const rateLimitMax = Number(env.RATE_LIMIT_MAX ?? "300"); if (!Number.isInteger(rateLimitMax) || rateLimitMax < 1) { throw new Error(`Invalid RATE_LIMIT_MAX: ${env.RATE_LIMIT_MAX}`); } const rateLimitWindowMs = Number(env.RATE_LIMIT_WINDOW_MS ?? "60000"); if (!Number.isInteger(rateLimitWindowMs) || rateLimitWindowMs < 1000) { throw new Error(`Invalid RATE_LIMIT_WINDOW_MS: ${env.RATE_LIMIT_WINDOW_MS}`); } return { host, port, storageDir, maxFileSize, fileTtlMs, rateLimitEnabled: boolFromEnv(env.RATE_LIMIT_ENABLED, true), rateLimitMax, rateLimitWindowMs, trustProxy: boolFromEnv(env.TRUST_PROXY, false), }; }