import { execFileSync } from 'node:child_process'; import { NestFactory } from '@nestjs/core'; import { apiEnvSchema, parseEnv } from '@dorfteich/shared'; import { Logger } from 'nestjs-pino'; import { AppModule } from './app.module'; import { AppConfig } from './config/app-config.service'; /** * Apply pending migrations before the application accepts traffic, so * self-hosters update by simply pulling a new image (ADR 0002). Prisma * serializes concurrent deploys with a database advisory lock. */ function runMigrations(): void { const prismaCli = require.resolve('prisma/build/index.js'); execFileSync(process.execPath, [prismaCli, 'migrate', 'deploy'], { stdio: 'inherit' }); } async function bootstrap(): Promise { // Validate the environment before doing anything with it; this throws a // readable list of problems and prevents a half-started process. const env = parseEnv(apiEnvSchema, process.env); if (env.MIGRATE_ON_START) { runMigrations(); } // bufferLogs holds early log lines until the pino logger is attached, // so even bootstrap errors come out as structured JSON. const app = await NestFactory.create(AppModule, { bufferLogs: true }); app.useLogger(app.get(Logger)); app.setGlobalPrefix('api/v1'); app.enableShutdownHooks(); const config = app.get(AppConfig); await app.listen(config.env.PORT); } void bootstrap();