101 lines
2.5 KiB
TypeScript
101 lines
2.5 KiB
TypeScript
import { pool } from '../db';
|
|
|
|
/**
|
|
* Migration System for God Mode
|
|
* Handles transactional execution of SQL migration files
|
|
*/
|
|
|
|
export interface MigrationResult {
|
|
success: boolean;
|
|
migrationsRun: number;
|
|
error?: string;
|
|
rolledBack?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Run multiple SQL commands in a single transaction
|
|
* Automatically rolls back if ANY command fails
|
|
*/
|
|
export async function runMigrations(sqlCommands: string[]): Promise<MigrationResult> {
|
|
const client = await pool.connect();
|
|
let migrationsRun = 0;
|
|
|
|
try {
|
|
await client.query('BEGIN');
|
|
console.log('🔱 [Migration] Starting transaction...');
|
|
|
|
for (const command of sqlCommands) {
|
|
// Skip empty commands or comments
|
|
const trimmed = command.trim();
|
|
if (!trimmed || trimmed.startsWith('--')) {
|
|
continue;
|
|
}
|
|
|
|
console.log(`[Migration] Executing: ${trimmed.substring(0, 100)}...`);
|
|
await client.query(trimmed);
|
|
migrationsRun++;
|
|
}
|
|
|
|
await client.query('COMMIT');
|
|
console.log(`✅ [Migration] Successfully committed ${migrationsRun} migrations`);
|
|
|
|
return {
|
|
success: true,
|
|
migrationsRun
|
|
};
|
|
|
|
} catch (error: any) {
|
|
await client.query('ROLLBACK');
|
|
console.error('❌ [Migration] Error - Rolling back all changes:', error.message);
|
|
|
|
return {
|
|
success: false,
|
|
migrationsRun,
|
|
error: error.message,
|
|
rolledBack: true
|
|
};
|
|
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run a single large SQL file (like migrations)
|
|
* Splits by semicolon and runs each statement in transaction
|
|
*/
|
|
export async function runMigrationFile(sqlContent: string): Promise<MigrationResult> {
|
|
// Split by semicolon, but be smart about it
|
|
const statements = sqlContent
|
|
.split(';')
|
|
.map(s => s.trim())
|
|
.filter(s => s.length > 0);
|
|
|
|
return runMigrations(statements);
|
|
}
|
|
|
|
/**
|
|
* Check if migrations have been run
|
|
*/
|
|
export async function getMigrationStatus(): Promise<{
|
|
tables: string[];
|
|
lastMigration?: Date;
|
|
}> {
|
|
try {
|
|
const result = await pool.query(`
|
|
SELECT table_name
|
|
FROM information_schema.tables
|
|
WHERE table_schema = 'public'
|
|
ORDER BY table_name
|
|
`);
|
|
|
|
return {
|
|
tables: result.rows.map((r: { table_name: string }) => r.table_name)
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
tables: []
|
|
};
|
|
}
|
|
}
|