import { readFileSync, writeFileSync } from "node:fs"; export interface ConfigStore { read(): Record; write(root: Record): void; } export type ConfigSource = | { configPath: string; configStore?: never; } | { configPath?: never; configStore: ConfigStore; }; function cloneConfig(root: Record): Record { return JSON.parse(JSON.stringify(root)) as Record; } function ensureConfigRoot(value: unknown, source: string): Record { if (!value || typeof value !== "object" || Array.isArray(value)) { throw new Error(`Invalid config.json shape at ${source}`); } return value as Record; } export function createFileConfigStore(configPath: string): ConfigStore { return { read() { const raw = readFileSync(configPath, "utf-8"); return ensureConfigRoot(JSON.parse(raw) as unknown, configPath); }, write(root) { writeFileSync(configPath, `${JSON.stringify(root, null, 2)}\n`, "utf-8"); }, }; } export function createMemoryConfigStore( initialRoot: Record, ): ConfigStore & { snapshot(): Record } { let current = cloneConfig(initialRoot); return { read() { return cloneConfig(current); }, write(root) { current = cloneConfig(root); }, snapshot() { return cloneConfig(current); }, }; } export function getConfigStore(source: ConfigSource): ConfigStore { if (source.configStore) { return source.configStore; } return createFileConfigStore(source.configPath); }