This commit is contained in:
2026-05-14 19:24:50 +00:00
parent af0628867f
commit a7f218e182
63 changed files with 10539 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
import type { FastifyInstance } from 'fastify';
import { z } from 'zod';
import type { Sql } from '../db.js';
export async function getSetting<T = unknown>(
sql: Sql,
key: string
): Promise<T | null> {
const rows = await sql<{ value: T }[]>`SELECT value FROM settings WHERE key = ${key}`;
return rows[0]?.value ?? null;
}
export async function setSetting(
sql: Sql,
key: string,
value: unknown
): Promise<void> {
await sql`
INSERT INTO settings (key, value)
VALUES (${key}, ${sql.json(value as never)})
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value
`;
}
const PatchBody = z.record(z.string(), z.unknown());
export function registerSettingsRoutes(app: FastifyInstance, sql: Sql): void {
app.get('/api/settings', async () => {
const rows = await sql<{ key: string; value: unknown }[]>`SELECT key, value FROM settings`;
const out: Record<string, unknown> = {};
for (const r of rows) out[r.key] = r.value;
return out;
});
app.patch('/api/settings', async (req, reply) => {
const parsed = PatchBody.safeParse(req.body);
if (!parsed.success) {
reply.code(400);
return { error: 'invalid body', details: parsed.error.flatten() };
}
for (const [k, v] of Object.entries(parsed.data)) {
await setSetting(sql, k, v);
}
const rows = await sql<{ key: string; value: unknown }[]>`SELECT key, value FROM settings`;
const out: Record<string, unknown> = {};
for (const r of rows) out[r.key] = r.value;
return out;
});
}