import { db, now } from '../db.js'; import { config } from '../config.js'; const runtimeEditableEnvKeys = new Set(['powershell_bin']); export function getSetting(key) { const row = db.prepare('SELECT value FROM settings WHERE key = ?').get(key); return row ? row.value : undefined; } export function getBooleanSetting(key, fallback) { const value = getSetting(key); if (value === undefined || value === '') return fallback; return String(value).toLowerCase() === 'true'; } export function getStringSetting(key, fallback = '') { const value = getSetting(key); const normalized = String(value ?? '').trim(); return normalized || fallback; } // Effective CORS allow-list: admin-editable `trusted_origins` merged with the // built-in localhost defaults so the dev experience never locks itself out. export function effectiveTrustedOrigins() { const raw = getSetting('trusted_origins'); const fromDb = String(raw || '').split(',').map((origin) => origin.trim()).filter(Boolean); return [...new Set([...fromDb, ...config.clientOrigins])]; } export function settingsPayload() { const settings = {}; for (const row of db.prepare('SELECT * FROM settings ORDER BY key').all()) { settings[row.key] = { value: row.value, source: row.source, updatedAt: row.updated_at }; } return settings; } export function updateSettings(payload) { const entries = Object.entries(payload || {}).filter(([key]) => /^[a-z0-9_]+$/i.test(key)); const sourceOf = db.prepare('SELECT source FROM settings WHERE key = ?'); const stmt = db.prepare(` INSERT INTO settings (key, value, source, updated_at) VALUES (?, ?, 'db', ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value, source = 'db', updated_at = excluded.updated_at `); for (const [key, value] of entries) { // Env-pinned settings are owned by the deployment environment; ignore // attempts to override them so the UI and process never disagree. if (sourceOf.get(key)?.source === 'env' && !runtimeEditableEnvKeys.has(key)) continue; stmt.run(key, String(value ?? ''), now()); } return settingsPayload(); }