From 2fb81a6d1a05a083c21c1f53eeda5f8acf27233c Mon Sep 17 00:00:00 2001 From: Tiago Yamamoto Date: Wed, 24 Dec 2025 10:47:25 -0300 Subject: [PATCH] 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 --- seeder-api/package.json | 9 ++++-- seeder-api/src/migrate.js | 58 ++++++++++++++++++++++++++++++++++----- start.sh | 23 ++-------------- 3 files changed, 61 insertions(+), 29 deletions(-) diff --git a/seeder-api/package.json b/seeder-api/package.json index cfc4c6f..53124c6 100644 --- a/seeder-api/package.json +++ b/seeder-api/package.json @@ -7,11 +7,16 @@ "scripts": { "seed": "node src/index.js", "seed:reset": "node src/index.js --reset", + "migrate": "node src/migrate.js", "seed:users": "node src/seeders/users.js", "seed:companies": "node src/seeders/companies.js", "seed:jobs": "node src/seeders/jobs.js" }, - "keywords": ["seeder", "jobs", "database"], + "keywords": [ + "seeder", + "jobs", + "database" + ], "author": "", "license": "MIT", "dependencies": { @@ -19,4 +24,4 @@ "bcrypt": "^5.1.1", "dotenv": "^16.3.1" } -} +} \ No newline at end of file diff --git a/seeder-api/src/migrate.js b/seeder-api/src/migrate.js index b897d9a..cf8994f 100644 --- a/seeder-api/src/migrate.js +++ b/seeder-api/src/migrate.js @@ -1,6 +1,6 @@ import fs from 'fs'; import path from 'path'; -import { pool } from './db.js'; +import { pool, testConnection, closePool } from './db.js'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); @@ -9,24 +9,68 @@ const __dirname = path.dirname(__filename); const MIGRATIONS_DIR = path.join(__dirname, '../../backend/migrations'); async function runMigrations() { - console.log('📦 Running migrations from:', MIGRATIONS_DIR); + 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(` ▶️ Executing ${file}...`); + console.log(`🔹 Running: ${file}`); const sql = fs.readFileSync(path.join(MIGRATIONS_DIR, file), 'utf8'); - await pool.query(sql); + + 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('✅ All migrations executed successfully'); + 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('❌ Error running migrations:', error); + console.error('❌ Migration failed:', error.message); + process.exit(1); } finally { - await pool.end(); + await closePool(); } } diff --git a/start.sh b/start.sh index a46a049..1308999 100755 --- a/start.sh +++ b/start.sh @@ -164,26 +164,9 @@ case $choice in 4) echo -e "\n${GREEN}🗄️ Running Migrations...${NC}\n" - cd backend - - # Load DB config from .env - if [ -f .env ]; then - source .env - fi - - DB_HOST=${DB_HOST:-localhost} - DB_PORT=${DB_PORT:-5432} - DB_USER=${DB_USER:-postgres} - DB_NAME=${DB_NAME:-gohorsejobs} - - echo -e "${BLUE}🔹 Connecting to ${DB_HOST}:${DB_PORT}/${DB_NAME}...${NC}" - - for file in migrations/*.sql; do - echo -e "${YELLOW}🔹 Running: $(basename $file)${NC}" - PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -p $DB_PORT -U $DB_USER -d $DB_NAME -f "$file" 2>&1 | head -5 - done - - echo -e "\n${GREEN}✅ Migrations completed!${NC}" + cd seeder-api + [ ! -d "node_modules" ] && npm install + npm run migrate ;; 5)