import db from '../config/database.js'; import logger from '../utils/logger.js'; const ALLOWED_TABLES = new Set([ 'users', 'crypto_wallets', 'transactions', 'products', 'purchases', 'locations', 'categories' ]); export const checkColumnExists = async (tableName, columnName) => { if (!ALLOWED_TABLES.has(tableName)) { throw new Error(`Invalid table name: ${tableName}`); } try { const result = await db.allAsync(`PRAGMA table_info(${tableName})`); return result.some(column => column.name === columnName); } catch (error) { logger.error({ err: error, tableName, columnName }, 'Error checking column'); return false; } }; export const cleanUpInvalidForeignKeys = async () => { try { await db.runAsync(`DELETE FROM crypto_wallets WHERE user_id NOT IN (SELECT id FROM users)`); logger.info('Cleaned up invalid foreign key references in crypto_wallets table'); } catch (error) { logger.error({ err: error }, 'Error cleaning up invalid foreign key references'); } }; export async function runMigrations() { await db.runAsync(`CREATE TABLE IF NOT EXISTS _meta (key TEXT PRIMARY KEY, value TEXT)`); const row = await db.getAsync(`SELECT value FROM _meta WHERE key = 'schema_version'`); const currentVersion = row ? parseInt(row.value, 10) : 0; const migrations = [ (await import('./001_initial_schema.js')).default, (await import('./002_add_columns.js')).default, (await import('./003_add_indexes.js')).default, (await import('./004_user_states.js')).default, (await import('./005_audit_log.js')).default, ]; for (let i = currentVersion; i < migrations.length; i++) { logger.info({ migration: i + 1, total: migrations.length }, 'Running migration'); if (i === 1) { await migrations[i](db, checkColumnExists); } else { await migrations[i](db); } await db.runAsync( `INSERT OR REPLACE INTO _meta (key, value) VALUES ('schema_version', ?)`, [String(i + 1)] ); } logger.info({ schemaVersion: migrations.length }, 'Migrations complete'); }