import { Pool, type QueryResultRow } from "pg"; const pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 10, idleTimeoutMillis: 30_000, connectionTimeoutMillis: 10_000, }); export type SqlValue = string | number | boolean | null | Date; export async function sql( strings: TemplateStringsArray, ...values: SqlValue[] ): Promise { const text = strings.reduce( (acc, chunk, i) => acc + chunk + (i < values.length ? `$${i + 1}` : ""), "", ); const result = await pool.query(text, values); return result.rows; } export async function query( text: string, values: SqlValue[] = [], ): Promise { const result = await pool.query(text, values); return result.rows; } export async function transaction( callback: ( tx: ( strings: TemplateStringsArray, ...values: SqlValue[] ) => Promise, ) => Promise, ): Promise { const client = await pool.connect(); try { await client.query("BEGIN"); const tx = async ( strings: TemplateStringsArray, ...values: SqlValue[] ) => { const text = strings.reduce( (acc, chunk, i) => acc + chunk + (i < values.length ? `$${i + 1}` : ""), "", ); const result = await client.query(text, values); return result.rows; }; const out = await callback(tx); await client.query("COMMIT"); return out; } catch (error) { await client.query("ROLLBACK"); throw error; } finally { client.release(); } }