import { promises as fs } from "node:fs"; import path from "node:path"; import type { AppData } from "@/modules/core/types"; const DATA_DIR = process.env.TEATEA_DATA_DIR ?? path.join(process.cwd(), ".data"); const DATA_FILE = path.join(DATA_DIR, "teatea.json"); function createEmptyData(): AppData { return { accounts: [], sessions: [], elders: [], auditLogs: [], }; } function normalizeData(data: Partial): AppData { return { accounts: Array.isArray(data.accounts) ? data.accounts : [], sessions: Array.isArray(data.sessions) ? data.sessions : [], elders: Array.isArray(data.elders) ? data.elders : [], auditLogs: Array.isArray(data.auditLogs) ? data.auditLogs : [], }; } function isMissingFileError(error: unknown): boolean { return ( typeof error === "object" && error !== null && "code" in error && (error as { code?: unknown }).code === "ENOENT" ); } export async function readData(): Promise { try { const raw = await fs.readFile(DATA_FILE, "utf8"); const parsed = JSON.parse(raw) as Partial; return normalizeData(parsed); } catch (error) { if (isMissingFileError(error)) { return createEmptyData(); } throw error; } } export async function writeData(data: AppData): Promise { await fs.mkdir(DATA_DIR, { recursive: true }); const temporaryFile = `${DATA_FILE}.tmp`; await fs.writeFile(temporaryFile, JSON.stringify(data, null, 2), "utf8"); await fs.rename(temporaryFile, DATA_FILE); } export async function updateData(mutator: (data: AppData) => T): Promise { const data = await readData(); const result = mutator(data); await writeData(data); return result; }