import { readdirSync, readFileSync } from "node:fs" import { dirname, join } from "node:path" import { fileURLToPath } from "node:url" import type { Pool } from "pg" const FIRST_MIGRATION = "0000_postgresql.sql" function migrationsDir(): string { const here = dirname(fileURLToPath(import.meta.url)) const candidates = [ join(here, "..", "..", "drizzle"), join(process.cwd(), "drizzle"), join(process.cwd(), "backend", "drizzle"), ] for (const dir of candidates) { try { readFileSync(join(dir, FIRST_MIGRATION), "utf8") return dir } catch { /* try next */ } } throw new Error("Не найден backend/drizzle/0000_postgresql.sql") } function migrationId(file: string): string { return file.replace(/\.sql$/i, "") } export async function applySqlMigrations(pool: Pool): Promise { await pool.query(` CREATE TABLE IF NOT EXISTS schema_migrations ( id TEXT PRIMARY KEY, applied_at TIMESTAMPTZ NOT NULL DEFAULT now() ) `) const dir = migrationsDir() const files = readdirSync(dir) .filter((f) => /^\d{4}_.+\.sql$/i.test(f)) .sort((a, b) => a.localeCompare(b)) const applied = new Set( (await pool.query<{ id: string }>(`SELECT id FROM schema_migrations`)).rows.map((r) => r.id), ) for (const file of files) { const id = migrationId(file) if (applied.has(id)) continue const sql = readFileSync(join(dir, file), "utf8") await pool.query(sql) await pool.query( `INSERT INTO schema_migrations (id) VALUES ($1) ON CONFLICT (id) DO NOTHING`, [id], ) } }