import fs from 'node:fs'; import path from 'node:path'; export function createJsonStateStore({ stateDir, fileName, initialState = {} }) { if (!stateDir) throw new Error('Missing stateDir'); if (!fileName) throw new Error('Missing fileName'); fs.mkdirSync(stateDir, { recursive: true }); const filePath = path.join(stateDir, fileName); const state = loadState(filePath, initialState); return { getState() { return state; }, setState(nextState) { replaceState(state, nextState); persistState(filePath, state); return state; }, update(mutator) { const nextState = mutator(structuredClone(state)); replaceState(state, nextState); persistState(filePath, state); return state; }, }; } function replaceState(target, nextState) { const source = nextState === target ? structuredClone(nextState) : (nextState || {}); for (const key of Object.keys(target)) delete target[key]; Object.assign(target, source); } function loadState(filePath, initialState) { if (!fs.existsSync(filePath)) return structuredClone(initialState); try { return { ...structuredClone(initialState), ...JSON.parse(fs.readFileSync(filePath, 'utf8')), }; } catch { return structuredClone(initialState); } } function persistState(filePath, state) { const tempPath = `${filePath}.tmp`; fs.writeFileSync(tempPath, JSON.stringify(state, null, 2)); fs.renameSync(tempPath, filePath); }