// Tiny JSON-file persistence layer. No external DB, no config. const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); const DB_PATH = path.join(__dirname, '..', 'data', 'db.json'); let db = null; let saveTimer = null; function uid(len = 12) { return crypto.randomBytes(len).toString('base64url').slice(0, len); } function load() { if (fs.existsSync(DB_PATH)) { try { db = JSON.parse(fs.readFileSync(DB_PATH, 'utf8')); } catch (e) { console.error('db corrupt, starting fresh:', e.message); db = null; } } if (!db) { db = { users: {}, games: {}, sessions: {}, catalog: [] }; } return db; } function get() { if (!db) load(); return db; } function save() { // Debounced write so rapid studio ops don't hammer the disk. if (saveTimer) return; saveTimer = setTimeout(() => { saveTimer = null; fs.writeFileSync(DB_PATH, JSON.stringify(db)); }, 500); } function saveNow() { if (saveTimer) { clearTimeout(saveTimer); saveTimer = null; } fs.writeFileSync(DB_PATH, JSON.stringify(db)); } function findUserByName(username) { const u = Object.values(get().users).find( (x) => x.username.toLowerCase() === String(username).toLowerCase() ); return u || null; } function publicUser(u) { if (!u) return null; return { id: u.id, username: u.username, avatar: u.avatar, created: u.created, stats: u.stats, system: !!u.system, }; } module.exports = { get, load, save, saveNow, uid, findUserByName, publicUser };