feat: auto-run SQL migrations and one-time seed on boot
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { execFile } from 'child_process';
|
||||
import { existsSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { promisify } from 'util';
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { runMigrations, runOnce } from './migrate';
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
function resolveSeedScript(): string | undefined {
|
||||
const candidates = [
|
||||
process.env.SEED_SCRIPT,
|
||||
join(process.cwd(), 'seed.js'),
|
||||
join(__dirname, '..', '..', 'seed.js'),
|
||||
].filter((p): p is string => Boolean(p));
|
||||
|
||||
return candidates.find((file) => existsSync(file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs pending SQL migrations before Nest boots, then seeds once.
|
||||
*
|
||||
* Seeding is gated on a marker row written only after the seed succeeds, so an
|
||||
* interrupted seed is retried on the next boot (the seed itself upserts).
|
||||
* Set RUN_MIGRATIONS=false or RUN_SEED=false to skip.
|
||||
*/
|
||||
export async function prepareDatabase(): Promise<void> {
|
||||
if (process.env.RUN_MIGRATIONS === 'false') return;
|
||||
|
||||
const logger = new Logger('DatabaseBootstrap');
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
try {
|
||||
const { applied } = await runMigrations(prisma);
|
||||
|
||||
if (applied.length > 0) {
|
||||
logger.log(`Applied migrations: ${applied.join(', ')}`);
|
||||
} else {
|
||||
logger.log('No pending migrations');
|
||||
}
|
||||
|
||||
if (process.env.RUN_SEED === 'false') return;
|
||||
|
||||
const seedScript = resolveSeedScript();
|
||||
if (!seedScript) {
|
||||
logger.warn('No seed script found — skipping seed');
|
||||
return;
|
||||
}
|
||||
|
||||
const seeded = await runOnce(prisma, 'seed:initial', async () => {
|
||||
const { stdout } = await execFileAsync(process.execPath, [seedScript]);
|
||||
if (stdout.trim()) logger.log(stdout.trim());
|
||||
});
|
||||
if (seeded) logger.log('Seed data inserted');
|
||||
} finally {
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user