const db = require('../db/db'); // Recursive deep merge: values from `patch` override `base`, objects are merged function deepMerge(base, patch) { const result = Object.assign({}, base); for (const key of Object.keys(patch)) { if ( patch[key] !== null && typeof patch[key] === 'object' && !Array.isArray(patch[key]) && typeof result[key] === 'object' && result[key] !== null && !Array.isArray(result[key]) ) { result[key] = deepMerge(result[key], patch[key]); } else { result[key] = patch[key]; } } return result; } /* ── GET /api/preferences ────────────────────────────────────────────────── */ function getPreferences(req, res) { const row = db.prepare('SELECT data FROM user_preferences WHERE user_id = ?').get(req.user.id); res.json(JSON.parse(row?.data || '{}')); } /* ── PATCH /api/preferences ──────────────────────────────────────────────── */ function patchPreferences(req, res) { if (!req.body || typeof req.body !== 'object' || Array.isArray(req.body)) { return res.status(400).json({ error: 'Body must be a JSON object' }); } const current = JSON.parse( db.prepare('SELECT data FROM user_preferences WHERE user_id = ?').get(req.user.id)?.data || '{}' ); const merged = deepMerge(current, req.body); if (JSON.stringify(merged).length > 50_000) return res.status(413).json({ error: 'Preferences too large (max 50KB)' }); db.prepare(` INSERT INTO user_preferences (user_id, data, updated_at) VALUES (?, ?, datetime('now')) ON CONFLICT(user_id) DO UPDATE SET data = excluded.data, updated_at = excluded.updated_at `).run(req.user.id, JSON.stringify(merged)); res.json(merged); } /* ── DELETE /api/preferences ─────────────────────────────────────────────── */ function resetPreferences(req, res) { db.prepare('DELETE FROM user_preferences WHERE user_id = ?').run(req.user.id); res.json({}); } module.exports = { getPreferences, patchPreferences, resetPreferences };