import crypto from "node:crypto"; import db from "./db.js"; const getStmt = db.prepare("SELECT value FROM settings WHERE key = ?"); const upsertStmt = db.prepare("INSERT INTO settings (key, value, updated_at) VALUES (?, ?, ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value, updated_at=excluded.updated_at"); const deleteStmt = db.prepare("DELETE FROM settings WHERE key = ?"); const listStmt = db.prepare("SELECT key, value FROM settings"); export type SettingKey = | "paperlessBaseUrl" | "paperlessExternalUrl" | "paperlessWebhookUrl" | "appExternalUrl" | "appLocale" | "paperlessToken" | "schedulerIntervalMinutes" | "alertDaysBefore" | "mailServer" | "mailPort" | "mailUsername" | "mailPassword" | "mailUseTls" | "mailFrom" | "mailTo" | "ntfyServerUrl" | "ntfyTopic" | "ntfyToken" | "ntfyPriority" | "authUsername" | "authPassword" | "icalSecret" | "aiEnabled" | "aiProvider" | "aiBaseUrl" | "aiModel" | "aiApiKey" | "aiSystemPrompt" | "aiTimeoutSeconds" | "aiMaxTokens" | "paperlessWebhookSecret" | "paperlessWorkflowId"; export type StoredSettings = Partial>; export function getSetting(key: SettingKey): T | undefined { const row = getStmt.get(key) as { value: string } | undefined; if (!row || typeof row.value !== "string") { return undefined; } try { return JSON.parse(row.value) as T; } catch (_error) { return undefined; } } export function setSetting(key: SettingKey, value: unknown): void { if (value === undefined || value === null || value === "") { deleteStmt.run(key); return; } const now = new Date().toISOString(); upsertStmt.run(key, JSON.stringify(value), now); } export function removeSetting(key: SettingKey): void { deleteStmt.run(key); } export function listSettings(): StoredSettings { const rows = listStmt.all() as Array<{ key: string; value: string }>; const result: StoredSettings = {}; for (const row of rows) { try { result[row.key as SettingKey] = JSON.parse(row.value); } catch (_error) { // ignore bad data } } return result; } export function ensureSetting(key: SettingKey, generator: () => unknown): unknown { const existing = getSetting(key); if (existing !== undefined) { return existing; } const value = generator(); setSetting(key, value); return value; } export function generateSecret(length = 32): string { return crypto.randomBytes(length).toString("hex"); }