- 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
77 lines
2.6 KiB
JavaScript
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();
|