import { existsSync, readFileSync } from "node:fs"; export interface NormalizedConfigResult { value: T; warnings?: string[]; } export interface LoadJsonConfigFileOptions { path: string; fallback: T; normalize: (raw: unknown) => NormalizedConfigResult; warn?: (message: string) => void; } export function loadJsonConfigFile({ path, fallback, normalize, warn }: LoadJsonConfigFileOptions): T { if (!existsSync(path)) { return structuredClone(fallback); } let raw: unknown; try { raw = JSON.parse(readFileSync(path, "utf8")) as unknown; } catch (error) { const detail = error instanceof Error ? error.message : String(error); warn?.(`Failed to parse config ${path}: ${detail}`); return structuredClone(fallback); } try { const normalized = normalize(raw); for (const message of normalized.warnings ?? []) { warn?.(message); } return normalized.value; } catch (error) { const detail = error instanceof Error ? error.message : String(error); warn?.(`Failed to normalize config ${path}: ${detail}`); return structuredClone(fallback); } }