import { randomUUID } from 'node:crypto'; import { chmod, link, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'; import { dirname } from 'node:path'; import { canonicalJson } from '../control-plane/snapshots.ts'; export async function readJson(path: string): Promise { try { return JSON.parse(await readFile(path, 'utf8')) as T; } catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null; throw error; } } export async function atomicJson(path: string, value: unknown) { await mkdir(dirname(path), { recursive: true, mode: 0o700 }); const temporary = `${path}.${randomUUID()}.tmp`; await writeFile(temporary, `${canonicalJson(value)}\n`, { encoding: 'utf8', mode: 0o600 }); await chmod(temporary, 0o600); await rename(temporary, path); } export async function immutableJson(path: string, value: unknown) { await mkdir(dirname(path), { recursive: true, mode: 0o700 }); const temporary = `${path}.${randomUUID()}.tmp`; await writeFile(temporary, `${canonicalJson(value)}\n`, { encoding: 'utf8', mode: 0o600 }); await chmod(temporary, 0o600); try { await link(temporary, path); } catch (error) { if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error; await rm(temporary, { force: true }); return false; } await rm(temporary, { force: true }); return true; }