TypeScript 97.6%
SQL 1.4%
JavaScript 0.5%
1import { drizzle, type NodePgDatabase } from "drizzle-orm/node-postgres";2import pg from "pg";3import * as schema from "./schema";45export * from "./schema";6export * as schema from "./schema";7export { sql, eq, and, or, desc, asc, gte, lte, lt, gt, ne, inArray, isNull, isNotNull, count, sum, avg, max, like, ilike, between, notInArray } from "drizzle-orm";89export type Db = NodePgDatabase<typeof schema>;10export type Tx = Parameters<Parameters<Db["transaction"]>[0]>[0];1112let _pool: pg.Pool | null = null;13let _db: Db | null = null;1415// BIGINT → number (we never exceed 2^53 credits), NUMERIC → string (handled per use).16pg.types.setTypeParser(20, (v) => Number(v));1718export function getPool(): pg.Pool {19 if (!_pool) {20 const connectionString = process.env.DATABASE_URL ?? "postgres://localhost:5432/spinza";21 _pool = new pg.Pool({22 connectionString,23 max: Number(process.env.DB_POOL_MAX ?? 10),24 idleTimeoutMillis: 30_000,25 connectionTimeoutMillis: 10_000,26 });27 _pool.on("error", (err) => console.error("[db] pool error", err.message));28 }29 return _pool;30}3132export function getDb(): Db {33 if (!_db) _db = drizzle(getPool(), { schema, casing: "snake_case" });34 return _db;35}3637/** Lazily-initialised shared database handle. */38export const db: Db = new Proxy({} as Db, {39 get(_t, prop) {40 return (getDb() as unknown as Record<PropertyKey, unknown>)[prop];41 },42});4344export async function closeDb(): Promise<void> {45 if (_pool) {46 await _pool.end();47 _pool = null;48 _db = null;49 }50}5152export async function pingDb(): Promise<number> {53 const t = Date.now();54 await getPool().query("select 1");55 return Date.now() - t;56}57