import { drizzle as drizzlePg } from "drizzle-orm/postgres-js"; import { migrate as migratePg } from "drizzle-orm/postgres-js/migrator"; import postgres from "postgres"; import * as schema from "./schema/index.js"; export function createDb(url: string) { const sql = postgres(url); return drizzlePg(sql, { schema }); } export type MigrationBootstrapResult = | { migrated: true; reason: "migrated-empty-db"; tableCount: 0 } | { migrated: false; reason: "already-migrated"; tableCount: number } | { migrated: false; reason: "not-empty-no-migration-journal"; tableCount: number }; export async function migratePostgresIfEmpty(url: string): Promise { const sql = postgres(url, { max: 1 }); try { const journal = await sql<{ regclass: string | null }[]>` select to_regclass('public.__drizzle_migrations') as regclass `; const tableCountResult = await sql<{ count: number }[]>` select count(*)::int as count from information_schema.tables where table_schema = 'public' and table_type = 'BASE TABLE' `; const tableCount = tableCountResult[0]?.count ?? 0; if (journal[0]?.regclass) { return { migrated: false, reason: "already-migrated", tableCount }; } if (tableCount > 0) { return { migrated: false, reason: "not-empty-no-migration-journal", tableCount }; } const db = drizzlePg(sql); const migrationsFolder = new URL("./migrations", import.meta.url).pathname; await migratePg(db, { migrationsFolder }); return { migrated: true, reason: "migrated-empty-db", tableCount: 0 }; } finally { await sql.end(); } } export async function ensurePostgresDatabase( url: string, databaseName: string, ): Promise<"created" | "exists"> { if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(databaseName)) { throw new Error(`Unsafe database name: ${databaseName}`); } const sql = postgres(url, { max: 1 }); try { const existing = await sql<{ one: number }[]>` select 1 as one from pg_database where datname = ${databaseName} limit 1 `; if (existing.length > 0) return "exists"; await sql.unsafe(`create database "${databaseName}"`); return "created"; } finally { await sql.end(); } } export type Db = ReturnType;