spb/chat-spboucher-ai
Public
1import postgres from "postgres";2import { env } from "./env";34declare global {5 // eslint-disable-next-line no-var6 var __csa_sql: ReturnType<typeof postgres> | undefined;7}89export const sql =10 globalThis.__csa_sql ??11 postgres(env.DATABASE_URL, {12 max: 10,13 idle_timeout: 30,14 connect_timeout: 10,15 transform: { undefined: null },16 types: {17 // numeric → number18 numeric: { to: 1700, from: [1700], serialize: (x: number) => String(x), parse: (x: string) => Number(x) },19 },20 });2122if (process.env.NODE_ENV !== "production") globalThis.__csa_sql = sql;2324export type Sql = typeof sql;2526/** Serialize a number[] for a pgvector column. */27export function vec(v: number[]): string {28 return `[${v.join(",")}]`;29}3031export async function getSetting<T = unknown>(key: string, fallback: T): Promise<T> {32 const rows = await sql<{ value: T }[]>`SELECT value FROM settings WHERE key = ${key}`;33 return rows[0]?.value ?? fallback;34}3536export async function setSetting(key: string, value: unknown): Promise<void> {37 await sql`INSERT INTO settings (key, value, updated_at) VALUES (${key}, ${sql.json(value as never)}, now())38 ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = now()`;39}40