import { drizzle } from "drizzle-orm/postgres-js" import { Resource } from "@opencode/cloud-resource" export * from "drizzle-orm" import postgres from "postgres" const init = () => { const client = postgres({ idle_timeout: 30000, connect_timeout: 30000, host: Resource.Database.host, database: Resource.Database.database, user: Resource.Database.username, password: Resource.Database.password, port: Resource.Database.port, ssl: { rejectUnauthorized: false, }, max: 6, }) return drizzle(client, {}) } const createClient = init import { PgTransaction, type PgTransactionConfig } from "drizzle-orm/pg-core" import type { ExtractTablesWithRelations } from "drizzle-orm" import type { PostgresJsQueryResultHKT } from "drizzle-orm/postgres-js" import { Context } from "../context" import { memo } from "../util/memo" export namespace Database { export type Transaction = PgTransaction< PostgresJsQueryResultHKT, Record, ExtractTablesWithRelations> > export type TxOrDb = Transaction | ReturnType const TransactionContext = Context.create<{ tx: TxOrDb effects: (() => void | Promise)[] }>() export async function use(callback: (trx: TxOrDb) => Promise) { try { const { tx } = TransactionContext.use() return tx.transaction(callback) } catch (err) { if (err instanceof Context.NotFound) { const client = createClient() const effects: (() => void | Promise)[] = [] const result = await TransactionContext.provide( { effects, tx: client, }, () => callback(client), ) await Promise.all(effects.map((x) => x())) return result } throw err } } export async function fn(callback: (input: Input, trx: TxOrDb) => Promise) { return (input: Input) => use(async (tx) => callback(input, tx)) } export async function effect(effect: () => any | Promise) { try { const { effects } = TransactionContext.use() effects.push(effect) } catch { await effect() } } export async function transaction(callback: (tx: TxOrDb) => Promise, config?: PgTransactionConfig) { try { const { tx } = TransactionContext.use() return callback(tx) } catch (err) { if (err instanceof Context.NotFound) { const client = createClient() const effects: (() => void | Promise)[] = [] const result = await client.transaction(async (tx) => { return TransactionContext.provide({ tx, effects }, () => callback(tx)) }, config) await Promise.all(effects.map((x) => x())) return result } throw err } } }