diff options
| author | Frank <[email protected]> | 2025-08-08 13:22:54 -0400 |
|---|---|---|
| committer | Frank <[email protected]> | 2025-08-08 13:24:32 -0400 |
| commit | 183e0911b76025a1f2a82e979d9834fec2131d0e (patch) | |
| tree | 9987c1753bd64d1ce1d174ab397f1a8c681f642c /cloud/core/src/drizzle | |
| parent | c7bb19ad0712469063eab35589aa5d3602b0c5b1 (diff) | |
| download | opencode-183e0911b76025a1f2a82e979d9834fec2131d0e.tar.gz opencode-183e0911b76025a1f2a82e979d9834fec2131d0e.zip | |
wip: gateway
Diffstat (limited to 'cloud/core/src/drizzle')
| -rw-r--r-- | cloud/core/src/drizzle/index.ts | 94 | ||||
| -rw-r--r-- | cloud/core/src/drizzle/types.ts | 29 |
2 files changed, 123 insertions, 0 deletions
diff --git a/cloud/core/src/drizzle/index.ts b/cloud/core/src/drizzle/index.ts new file mode 100644 index 000000000..76220f2a2 --- /dev/null +++ b/cloud/core/src/drizzle/index.ts @@ -0,0 +1,94 @@ +import { drizzle } from "drizzle-orm/postgres-js" +import { Resource } from "sst" +export * from "drizzle-orm" +import postgres from "postgres" + +function createClient() { + 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: 1, + }) + + return drizzle(client, {}) +} + +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" + +export namespace Database { + export type Transaction = PgTransaction< + PostgresJsQueryResultHKT, + Record<string, unknown>, + ExtractTablesWithRelations<Record<string, unknown>> + > + + export type TxOrDb = Transaction | ReturnType<typeof createClient> + + const TransactionContext = Context.create<{ + tx: TxOrDb + effects: (() => void | Promise<void>)[] + }>() + + export async function use<T>(callback: (trx: TxOrDb) => Promise<T>) { + try { + const { tx } = TransactionContext.use() + return tx.transaction(callback) + } catch (err) { + if (err instanceof Context.NotFound) { + const client = createClient() + const effects: (() => void | Promise<void>)[] = [] + 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<Input, T>(callback: (input: Input, trx: TxOrDb) => Promise<T>) { + return (input: Input) => use(async (tx) => callback(input, tx)) + } + + export async function effect(effect: () => any | Promise<any>) { + try { + const { effects } = TransactionContext.use() + effects.push(effect) + } catch { + await effect() + } + } + + export async function transaction<T>(callback: (tx: TxOrDb) => Promise<T>, config?: PgTransactionConfig) { + try { + const { tx } = TransactionContext.use() + return callback(tx) + } catch (err) { + if (err instanceof Context.NotFound) { + const client = createClient() + const effects: (() => void | Promise<void>)[] = [] + 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 + } + } +} diff --git a/cloud/core/src/drizzle/types.ts b/cloud/core/src/drizzle/types.ts new file mode 100644 index 000000000..5ae95d011 --- /dev/null +++ b/cloud/core/src/drizzle/types.ts @@ -0,0 +1,29 @@ +import { bigint, timestamp, varchar } from "drizzle-orm/pg-core" + +export const ulid = (name: string) => varchar(name, { length: 30 }) + +export const workspaceColumns = { + get id() { + return ulid("id").notNull() + }, + get workspaceID() { + return ulid("workspace_id").notNull() + }, +} + +export const id = () => ulid("id").notNull() + +export const utc = (name: string) => + timestamp(name, { + withTimezone: true, + }) + +export const currency = (name: string) => + bigint(name, { + mode: "number", + }) + +export const timestamps = { + timeCreated: utc("time_created").notNull().defaultNow(), + timeDeleted: utc("time_deleted"), +} |
