97 lines
2.5 KiB
TypeScript
97 lines
2.5 KiB
TypeScript
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<Record<SettingKey, unknown>>;
|
|
|
|
export function getSetting<T = unknown>(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");
|
|
}
|