/** * Persistent JSON store — backed by ./data/store.json (Docker volume mount). * * Schema: * { * config: { eb_app_id, eb_private_key, gc_secret_id, gc_secret_key } | null, * gc_tokens: { [token]: { type: "access"|"refresh", expires_at } }, * institutions_cache: [...] | null, * institutions_cache_at: 0, * agreements: { [gc_id]: { id, created, institution_id, max_historical_days, * access_valid_for_days, access_scope } }, * requisitions: { [gc_id]: { id, created, status, institution_id, agreements, * accounts, reference, redirect, link, * eb_auth_id, eb_session_id } }, * accounts: { [gc_id]: { gc_id, eb_uid, institution_id, iban, currency, * owner_name, name, product, created, last_accessed } } * } */ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs'; import { dirname } from 'path'; const STORE_PATH = process.env.STORE_PATH || './data/store.json'; const EMPTY = () => ({ config: null, gc_tokens: {}, institutions_cache: null, institutions_cache_at: 0, agreements: {}, requisitions: {}, accounts: {}, }); let _store = null; export function load() { if (!existsSync(STORE_PATH)) return EMPTY(); try { return JSON.parse(readFileSync(STORE_PATH, 'utf8')); } catch { return EMPTY(); } } export function get() { if (!_store) _store = load(); return _store; } export function save() { const dir = dirname(STORE_PATH); mkdirSync(dir, { recursive: true }); writeFileSync(STORE_PATH, JSON.stringify(_store ?? EMPTY(), null, 2)); } /** Apply a mutation function and persist immediately. */ export function update(fn) { const s = get(); fn(s); save(); }