import { NestFactory } from '@nestjs/core'; import { ValidationPipe } from '@nestjs/common'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import { ConfigService } from '@nestjs/config'; import { Logger } from 'nestjs-pino'; import helmet from 'helmet'; import cookieParser from 'cookie-parser'; import { AppModule } from './app.module'; import { GlobalExceptionFilter } from './common/filters/http-exception.filter'; async function bootstrap() { const app = await NestFactory.create(AppModule, { bufferLogs: true }); // Set Pino as the logger app.useLogger(app.get(Logger)); const configService = app.get(ConfigService); const logger = app.get(Logger); // Security app.use(helmet()); app.getHttpAdapter().getInstance().disable('x-powered-by'); app.use(cookieParser()); // Behind reverse proxies (e.g., Nginx) to ensure correct IPs and secure cookies if (configService.get('TRUST_PROXY', 'false') === 'true') { const httpAdapter = app.getHttpAdapter(); const instance: any = httpAdapter.getInstance(); if (instance?.set) { instance.set('trust proxy', 1); } } // CORS app.enableCors({ origin: configService.get('CORS_ORIGIN', 'http://localhost:3000'), credentials: true, }); // Global validation pipe app.useGlobalPipes( new ValidationPipe({ transform: true, whitelist: true, forbidNonWhitelisted: true, }), ); // Global exception filter app.useGlobalFilters(new GlobalExceptionFilter()); // Ensure proper shutdown for Prisma/Redis and logger flush app.enableShutdownHooks(); const shutdown = async (signal: string) => { try { logger.warn(`Received ${signal}. Shutting down gracefully...`); await app.close(); if (typeof (logger as any).flush === 'function') { await (logger as any).flush(); } } catch (err) { // eslint-disable-next-line no-console console.error('Error during shutdown', err); } finally { process.exit(0); } }; process.on('SIGINT', () => shutdown('SIGINT')); process.on('SIGTERM', () => shutdown('SIGTERM')); // Global prefix app.setGlobalPrefix('api'); // Swagger documentation if (configService.get('NODE_ENV') !== 'production') { const config = new DocumentBuilder() .setTitle('Customer Portal API') .setDescription('Backend for Frontend API for customer portal') .setVersion('1.0') .addBearerAuth() .addCookieAuth('auth-cookie') .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api/docs', app, document); } const port = Number(configService.get('BFF_PORT', 4000)); await app.listen(port); logger.log(`🚀 BFF API running on: http://localhost:${port}/api`); if (configService.get('NODE_ENV') !== 'production') { logger.log(`📚 API Documentation: http://localhost:${port}/api/docs`); } } bootstrap();