import { readFileSync, readdirSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { PGlite } from '@electric-sql/pglite'; import { PGLiteSocketServer } from '@electric-sql/pglite-socket'; const here = dirname(fileURLToPath(import.meta.url)); const MIGRATIONS_DIR = join(here, '..', 'prisma', 'migrations'); /** Alle Migrationen in der Reihenfolge, in der Prisma sie anwenden würde. */ function migrationFiles(): string[] { return readdirSync(MIGRATIONS_DIR) .filter((entry) => /^\d/.test(entry)) .sort() .map((entry) => join(MIGRATIONS_DIR, entry, 'migration.sql')); } export interface TestDatabase { url: string; stop: () => Promise; } /** * Startet eine Postgres-Instanz im Speicher und stellt sie über einen lokalen * Port bereit, damit Prisma sich wie an eine echte Datenbank verbindet. * So laufen die Tests ohne Docker oder installiertes Postgres. */ export async function startTestDatabase(port: number): Promise { const db = await PGlite.create(); for (const file of migrationFiles()) { await db.exec(readFileSync(file, 'utf8')); } const server = new PGLiteSocketServer({ db, port, host: '127.0.0.1' }); await server.start(); return { // connection_limit=1, weil die Testinstanz immer nur eine Verbindung // gleichzeitig bedient. Echtes Postgres braucht die Einschränkung nicht. url: `postgresql://postgres:postgres@127.0.0.1:${port}/postgres?connection_limit=1`, stop: async () => { await server.stop(); await db.close(); }, }; }