Repository Public
1import postgres from "postgres";2import { env } from "./env";34declare global { var __spcalSql: ReturnType<typeof postgres> | undefined; }56export const sql = globalThis.__spcalSql ?? (globalThis.__spcalSql = postgres(env.databaseUrl, {7 max: 10, idle_timeout: 30, onnotice: () => {},8}));910export type Sql = typeof sql;11export type Tx = postgres.TransactionSql;12/** JSON value for a jsonb column. */13export const j = (v: unknown) => sql.json(v as never);1415/**16 * Runs `fn` in a transaction holding the owner's advisory lock. Every path that creates, confirms or moves an17 * appointment goes through here, so availability checks and writes for one owner are strictly serialised.18 */19export async function withOwnerLock<T>(userId: string, fn: (tx: Tx) => Promise<T>): Promise<T> {20 return sql.begin(async (tx) => {21 await tx`SELECT pg_advisory_xact_lock(hashtextextended(${"spcal:" + userId}, 0))`;22 return fn(tx);23 }) as Promise<T>;24}2526export const iso = (d: Date | string | null | undefined) => (d == null ? null : new Date(d).toISOString());27