refactor: auto-run DB migration at startup, robust schema.sql path resolution
This commit is contained in:
+46
-10
@@ -3,15 +3,51 @@ import { config } from '../env';
|
||||
import { getErrorMessage } from '../utils/file';
|
||||
import logger from '../utils/logger';
|
||||
|
||||
const schemaSql = await Bun.file('schema.sql').text();
|
||||
const sql = postgres(config.databaseUrl, { max: 1 });
|
||||
/**
|
||||
* Run raw SQL migration from schema.sql.
|
||||
* Safe to call multiple times — all statements use IF NOT EXISTS.
|
||||
*/
|
||||
export const runMigration = async (): Promise<void> => {
|
||||
// In compiled dist: import.meta.dir = .../dist/
|
||||
// In source via bun --hot: import.meta.dir = .../src/db/
|
||||
const dir = import.meta.dir || '';
|
||||
const candidates = [
|
||||
dir + '/../../schema.sql', // from dist/
|
||||
dir + '/../schema.sql', // from src/ (bun --hot src/index.ts)
|
||||
dir + '/../schema.sql', // from src/db/ (bun --hot src/db/migrate.ts)
|
||||
dir + '/schema.sql', // from src/ (bun run db:migrate)
|
||||
];
|
||||
|
||||
try {
|
||||
await sql.unsafe(schemaSql);
|
||||
logger.info('Database migration completed');
|
||||
} catch (error: unknown) {
|
||||
logger.error('Database migration failed', { error: getErrorMessage(error) });
|
||||
process.exitCode = 1;
|
||||
} finally {
|
||||
await sql.end();
|
||||
let schemaSql: string | null = null;
|
||||
for (const p of candidates) {
|
||||
const file = Bun.file(p);
|
||||
const exists = await file.exists();
|
||||
if (exists) {
|
||||
schemaSql = await file.text();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!schemaSql) {
|
||||
logger.error('Migration failed: schema.sql not found (tried ' + candidates.join(', ') + ')');
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
const sql = postgres(config.databaseUrl, { max: 1 });
|
||||
|
||||
try {
|
||||
await sql.unsafe(schemaSql);
|
||||
logger.info('Database migration completed');
|
||||
} catch (error: unknown) {
|
||||
logger.error('Database migration failed', { error: getErrorMessage(error) });
|
||||
process.exitCode = 1;
|
||||
} finally {
|
||||
await sql.end();
|
||||
}
|
||||
};
|
||||
|
||||
// When run directly: `bun src/db/migrate.ts` or `bun dist/migrate.js`
|
||||
if (import.meta.path === Bun.main) {
|
||||
await runMigration();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,22 @@ import logger from './utils/logger';
|
||||
import { metricsCollector } from './utils/metrics';
|
||||
import { cleanupRateLimitCache, withRateLimit } from './utils/rateLimit';
|
||||
|
||||
// ─── Auto-run migration at startup ──────────────────────────────────────────
|
||||
try {
|
||||
const { runMigration } = await import('./db/migrate');
|
||||
await runMigration();
|
||||
} catch {
|
||||
logger.warn('Auto-migration skipped (non-fatal)');
|
||||
}
|
||||
|
||||
// ─── Auto-run migration at startup ───
|
||||
try {
|
||||
await import('./db/migrate');
|
||||
} catch {
|
||||
// migrate.ts calls process.exit(1) on failure — if it throws, log and continue
|
||||
logger.warn('Auto-migration warning (non-fatal)');
|
||||
}
|
||||
|
||||
const server = serve({
|
||||
port: config.port,
|
||||
routes: {
|
||||
|
||||
Reference in New Issue
Block a user