import pg from "pg"; import { drizzle } from "drizzle-orm/node-postgres"; import * as schema from "./schema/index.js"; export type Database = ReturnType["db"]; let sharedPool: pg.Pool | undefined; /** * Skapar en databasklient. API och worker delar mönster men äger varsin pool. * DATABASE_URL pekar på appens separata databas med egen minimalprivilegie-användare * (minsta möjliga privilegier, spec §52). */ export function createDatabase(connectionString?: string) { const isTest = process.env.NODE_ENV === "test" || process.env.VITEST !== undefined; const url = connectionString ?? (isTest ? process.env.TEST_DATABASE_URL : process.env.DATABASE_URL); if (!url) { if (isTest) { throw new Error( "Sätt TEST_DATABASE_URL till en dedikerad testdatabas. Tester får aldrig använda DATABASE_URL.", ); } throw new Error("Missing DATABASE_URL. Set it in your .env or environment before starting the app."); } const pool = new pg.Pool({ connectionString: url, max: Number(process.env.DATABASE_POOL_MAX ?? 10), idleTimeoutMillis: 30_000, connectionTimeoutMillis: 10_000, }); const db = drizzle(pool, { schema, casing: "snake_case" }); return { db, pool }; } /** Singleton för processer som bara behöver en anslutning. */ export function getDatabase() { if (!sharedPool) { const { db, pool } = createDatabase(); sharedPool = pool; sharedDb = db; } return sharedDb!; } let sharedDb: Database | undefined; export async function closeDatabase(): Promise { if (sharedPool) { await sharedPool.end(); sharedPool = undefined; sharedDb = undefined; } } export { schema };