From 183e0911b76025a1f2a82e979d9834fec2131d0e Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 8 Aug 2025 13:22:54 -0400 Subject: wip: gateway --- cloud/core/src/drizzle/index.ts | 94 +++++++++++++++++++++++++++++++++++++++++ cloud/core/src/drizzle/types.ts | 29 +++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 cloud/core/src/drizzle/index.ts create mode 100644 cloud/core/src/drizzle/types.ts (limited to 'cloud/core/src/drizzle') 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, + 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 + } + } +} 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"), +} -- cgit v1.2.3