import { credential } from 'kody:runtime' import { NEON_SQL_URL } from './config.ts' /** * Minimal Neon serverless-HTTP client. The `neon-postgres` credential injects the * Postgres connection string as the `Neon-Connection-String` header, only to * the approved Neon endpoint host. Code never sees the value. */ export type Row = Record export type Query = { query: string; params?: Array } async function post(body: unknown, batch: boolean) { const db = await credential('neon-postgres') const response = await db.fetch(NEON_SQL_URL, { method: 'POST', headers: { 'content-type': 'application/json', 'Neon-Array-Mode': 'false', 'Neon-Raw-Text-Output': 'true', ...(batch ? { 'Neon-Batch-Isolation-Level': 'ReadCommitted' } : {}), }, body: JSON.stringify(body), }) const text = await response.text() if (!response.ok) { let message = text.slice(0, 300) try { message = (JSON.parse(text) as { message?: string }).message ?? message } catch {} throw new Error(`Database error (${response.status}): ${message}`) } return JSON.parse(text) as unknown } export async function sql(query: string, params: Array = []) { const out = (await post({ query, params }, false)) as { rows: Array } return out.rows } /** Run queries in one transaction; returns rows per query. */ export async function transaction(queries: Array) { if (queries.length === 0) return [] const out = (await post( { queries: queries.map((q) => ({ query: q.query, params: q.params ?? [] })) }, true, )) as { results: Array<{ rows: Array }> } return out.results.map((r) => r.rows) } export const num = (value: unknown) => (value == null ? 0 : Number(value))