From 9ec3e97d9e0af32ab456a01e09e2df21ff4c726f Mon Sep 17 00:00:00 2001 From: jackiettran <41605212+jackiettran@users.noreply.github.com> Date: Tue, 25 Nov 2025 17:53:49 -0500 Subject: [PATCH] remove sync alter true, add pending migration check --- backend/scripts/manageAlphaInvitations.js | 4 +- backend/server.js | 20 ++++- backend/utils/checkMigrations.js | 96 +++++++++++++++++++++++ 3 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 backend/utils/checkMigrations.js diff --git a/backend/scripts/manageAlphaInvitations.js b/backend/scripts/manageAlphaInvitations.js index c41518f..0b877a3 100644 --- a/backend/scripts/manageAlphaInvitations.js +++ b/backend/scripts/manageAlphaInvitations.js @@ -353,8 +353,8 @@ async function main() { const command = args[0]; try { - // Sync database - await sequelize.sync(); + // Verify database connection + await sequelize.authenticate(); if (!command || command === "help") { console.log(` diff --git a/backend/server.js b/backend/server.js index 55d97e8..eb200c3 100644 --- a/backend/server.js +++ b/backend/server.js @@ -165,10 +165,23 @@ app.use(sanitizeError); const PORT = process.env.PORT || 5000; +const { checkPendingMigrations } = require("./utils/checkMigrations"); + sequelize - .sync({ alter: true }) + .authenticate() .then(async () => { - logger.info("Database synced successfully"); + logger.info("Database connection established successfully"); + + // Check for pending migrations + const pendingMigrations = await checkPendingMigrations(sequelize); + if (pendingMigrations.length > 0) { + logger.error( + `Found ${pendingMigrations.length} pending migration(s). Please run 'npm run db:migrate'`, + { pendingMigrations } + ); + process.exit(1); + } + logger.info("All migrations are up to date"); // Initialize email services and load templates try { @@ -209,8 +222,9 @@ sequelize }); }) .catch((err) => { - logger.error("Unable to sync database", { + logger.error("Unable to connect to database", { error: err.message, stack: err.stack, }); + process.exit(1); }); diff --git a/backend/utils/checkMigrations.js b/backend/utils/checkMigrations.js new file mode 100644 index 0000000..d9c2bc7 --- /dev/null +++ b/backend/utils/checkMigrations.js @@ -0,0 +1,96 @@ +const fs = require("fs"); +const path = require("path"); + +/** + * Check for pending database migrations + * + * Compares migration files in the filesystem against the SequelizeMeta table + * to determine which migrations have not yet been executed. + * + * @param {Sequelize} sequelize - Sequelize instance + * @returns {Promise} Array of pending migration filenames + */ +async function checkPendingMigrations(sequelize) { + const migrationsPath = path.resolve(__dirname, "..", "migrations"); + + // Get all migration files from filesystem + const migrationFiles = fs + .readdirSync(migrationsPath) + .filter((file) => file.endsWith(".js")) + .sort(); + + // Check if SequelizeMeta table exists + const [results] = await sequelize.query(` + SELECT EXISTS ( + SELECT FROM information_schema.tables + WHERE table_schema = 'public' + AND table_name = 'SequelizeMeta' + ) as exists + `); + + if (!results[0].exists) { + // No migrations have ever been run + return migrationFiles; + } + + // Get executed migrations from SequelizeMeta + const [executedMigrations] = await sequelize.query( + 'SELECT name FROM "SequelizeMeta" ORDER BY name' + ); + + const executedSet = new Set(executedMigrations.map((row) => row.name)); + + // Find migrations that haven't been executed + const pendingMigrations = migrationFiles.filter( + (file) => !executedSet.has(file) + ); + + return pendingMigrations; +} + +/** + * Get migration status summary + * + * @param {Sequelize} sequelize - Sequelize instance + * @returns {Promise<{executed: string[], pending: string[]}>} Migration status + */ +async function getMigrationStatus(sequelize) { + const migrationsPath = path.resolve(__dirname, "..", "migrations"); + + const migrationFiles = fs + .readdirSync(migrationsPath) + .filter((file) => file.endsWith(".js")) + .sort(); + + // Check if SequelizeMeta table exists + const [results] = await sequelize.query(` + SELECT EXISTS ( + SELECT FROM information_schema.tables + WHERE table_schema = 'public' + AND table_name = 'SequelizeMeta' + ) as exists + `); + + if (!results[0].exists) { + return { + executed: [], + pending: migrationFiles, + }; + } + + const [executedMigrations] = await sequelize.query( + 'SELECT name FROM "SequelizeMeta" ORDER BY name' + ); + + const executedSet = new Set(executedMigrations.map((row) => row.name)); + + return { + executed: migrationFiles.filter((file) => executedSet.has(file)), + pending: migrationFiles.filter((file) => !executedSet.has(file)), + }; +} + +module.exports = { + checkPendingMigrations, + getMigrationStatus, +};