refactor(arch): split database.js into migrations + connection module (#57)
- database.js: 292→42 lines (connection + async helpers only) - 001_initial_schema.js: 7 CREATE TABLE statements in transaction - 002_add_columns.js: 5 ALTER TABLE checks with checkColumnExists - 003_add_indexes.js: 6 CREATE INDEX statements - runner.js: versioned migration runner with _meta table - index.js: calls runMigrations() + cleanUpInvalidForeignKeys() - ALLOWED_TABLES whitelist preserved in runner.js - Schema version tracked in _meta table for idempotent runs
This commit is contained in:
56
src/migrations/runner.js
Normal file
56
src/migrations/runner.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import db from '../config/database.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) {
|
||||
console.error(`Error checking column ${columnName} in table ${tableName}:`, error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const cleanUpInvalidForeignKeys = async () => {
|
||||
try {
|
||||
await db.runAsync(`DELETE FROM crypto_wallets WHERE user_id NOT IN (SELECT id FROM users)`);
|
||||
console.log('Cleaned up invalid foreign key references in crypto_wallets table');
|
||||
} catch (error) {
|
||||
console.error('Error cleaning up invalid foreign key references:', error);
|
||||
}
|
||||
};
|
||||
|
||||
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,
|
||||
];
|
||||
|
||||
for (let i = currentVersion; i < migrations.length; i++) {
|
||||
console.log(`Running migration ${i + 1}/${migrations.length}...`);
|
||||
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)]
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`Migrations complete. Schema version: ${migrations.length}`);
|
||||
}
|
||||
Reference in New Issue
Block a user