import { BadRequestException, INestApplication, ValidationPipe, } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { NestFactory } from '@nestjs/core'; import { SwaggerModule } from '@nestjs/swagger'; import cookieParser from 'cookie-parser'; import { Logger } from 'nestjs-pino'; import { AppModule } from './app.module'; import { HttpExceptionFilter } from './common/filters/http-exception.filter'; import { StructuredLogger } from './common/logging/structured-logger.service'; import { Environment } from './config/env.validation'; import { shouldExposeSwagger } from './config/swagger.config'; import { API_PREFIX, createOpenApiDocument } from './openapi'; export function configureApp(app: INestApplication): void { const config = app.get>(ConfigService); const frontendOrigin = config.getOrThrow('FRONTEND_ORIGIN'); app.useLogger(app.get(Logger)); app.enableCors({ origin: frontendOrigin, credentials: true, exposedHeaders: ['X-Request-ID'], }); app.setGlobalPrefix(API_PREFIX); app.use(cookieParser()); app.useGlobalPipes( new ValidationPipe({ forbidUnknownValues: true, transform: true, whitelist: true, validationError: { target: false, value: false }, exceptionFactory: (message) => new BadRequestException({ message }), }), ); app.useGlobalFilters(new HttpExceptionFilter(app.get(StructuredLogger))); app.enableShutdownHooks(); } async function bootstrap() { const app = await NestFactory.create(AppModule, { bufferLogs: true }); configureApp(app); const config = app.get>(ConfigService); if (shouldExposeSwagger(process.env['NODE_ENV'])) { const document = createOpenApiDocument(app); SwaggerModule.setup('api/docs', app, document); } await app.listen(config.getOrThrow('PORT')); app.get(StructuredLogger).info('application.started', { service: 'wealth-ledger-backend', environment: process.env['NODE_ENV'] ?? 'development', }); } if (require.main === module) void bootstrap();