import 'dotenv/config'; import { readFileSync, readdirSync } from 'fs'; import { join } from 'path'; import { query, pool } from '../src/utils/db.js'; import { pino } from 'pino'; const log = pino({ name: 'migrate' }); async function main() { log.info('Running migrations...'); // Create migrations tracking table await query(` CREATE TABLE IF NOT EXISTS _migrations ( id SERIAL PRIMARY KEY, name VARCHAR(200) NOT NULL UNIQUE, applied_at TIMESTAMPTZ DEFAULT NOW() ) `); // Get applied migrations const applied = await query('SELECT name FROM _migrations ORDER BY id'); const appliedSet = new Set(applied.rows.map(r => r.name)); // Read migration files const migrationsDir = join(import.meta.dirname ?? '.', '..', 'migrations'); const files = readdirSync(migrationsDir) .filter(f => f.endsWith('.sql')) .sort(); for (const file of files) { if (appliedSet.has(file)) { log.info(`Skip (already applied): ${file}`); continue; } log.info(`Applying: ${file}`); const sql = readFileSync(join(migrationsDir, file), 'utf-8'); try { await query(sql); await query('INSERT INTO _migrations (name) VALUES ($1)', [file]); log.info(`Applied: ${file}`); } catch (err) { log.error({ err, file }, 'Migration failed'); process.exit(1); } } log.info('All migrations applied'); await pool.end(); process.exit(0); } main();