gohorsejobs/seeder-api/src/migrate.js
Tiago Yamamoto 2fb81a6d1a fix(migrations): use Node.js runner instead of psql
- Improve migrate.js with error handling for idempotent migrations
- Add 'npm run migrate' script to seeder-api/package.json
- Update start.sh option 4 to use Node.js-based migration runner
- Handles duplicate tables, columns, constraints gracefully
2025-12-24 10:47:25 -03:00

77 lines
2.6 KiB
JavaScript

import fs from 'fs';
import path from 'path';
import { pool, testConnection, closePool } from './db.js';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const MIGRATIONS_DIR = path.join(__dirname, '../../backend/migrations');
async function runMigrations() {
console.log('🗄️ Running Migrations...\n');
try {
const connected = await testConnection();
if (!connected) {
throw new Error('Could not connect to database');
}
console.log(`📁 Reading from: ${MIGRATIONS_DIR}\n`);
const files = fs.readdirSync(MIGRATIONS_DIR)
.filter(f => f.endsWith('.sql'))
.sort();
console.log(`📄 Found ${files.length} migration files\n`);
let success = 0;
let skipped = 0;
let failed = 0;
for (const file of files) {
console.log(`🔹 Running: ${file}`);
const sql = fs.readFileSync(path.join(MIGRATIONS_DIR, file), 'utf8');
try {
await pool.query(sql);
console.log(` ✅ Success`);
success++;
} catch (error) {
// Handle idempotent errors gracefully
if (error.code === '42P07') {
console.log(` ⏭️ Table already exists (skipped)`);
skipped++;
} else if (error.code === '42710') {
console.log(` ⏭️ Object already exists (skipped)`);
skipped++;
} else if (error.code === '23505') {
console.log(` ⏭️ Data already exists (skipped)`);
skipped++;
} else if (error.code === '42701') {
console.log(` ⏭️ Column already exists (skipped)`);
skipped++;
} else if (error.code === '42P16') {
console.log(` ⏭️ Constraint already exists (skipped)`);
skipped++;
} else {
console.error(` ❌ Error: ${error.message}`);
failed++;
}
}
}
console.log('\n' + '═'.repeat(50));
console.log(`✅ Migrations completed!`);
console.log(` Success: ${success} | Skipped: ${skipped} | Failed: ${failed}`);
console.log('═'.repeat(50));
} catch (error) {
console.error('❌ Migration failed:', error.message);
process.exit(1);
} finally {
await closePool();
}
}
runMigrations();