import { ValidationPipe } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { NestFactory } from '@nestjs/core'; import { NestExpressApplication } from '@nestjs/platform-express'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import helmet from 'helmet'; import { join } from 'path'; import { AppModule } from './app.module'; import { AllExceptionsFilter } from './common/filters/all-exceptions.filter'; import { ResponseInterceptor } from './common/interceptors/response.interceptor'; import { PrismaService } from './prisma/prisma.service'; async function bootstrap() { const app = await NestFactory.create(AppModule); const configService = app.get(ConfigService); // Security Headers app.use( helmet({ crossOriginResourcePolicy: { policy: 'cross-origin' }, }), ); // CORS const adminOrigin = configService.get('CORS_ADMIN_ORIGIN', 'http://localhost:5173'); const clientOrigin = configService.get('CORS_CLIENT_ORIGIN', 'http://localhost:5174'); app.enableCors({ origin: [adminOrigin, clientOrigin], credentials: true, }); // Global Prefix app.setGlobalPrefix('api'); // Serve static uploads const uploadRoot = configService.get('STORAGE_LOCAL_ROOT', './uploads'); app.useStaticAssets(join(process.cwd(), uploadRoot), { prefix: '/uploads/', }); // Global Validation Pipe app.useGlobalPipes( new ValidationPipe({ whitelist: true, forbidNonWhitelisted: false, transform: true, transformOptions: { enableImplicitConversion: true, }, }), ); // Global Filter & Interceptor app.useGlobalFilters(new AllExceptionsFilter()); app.useGlobalInterceptors(new ResponseInterceptor()); // Prisma Shutdown Hooks const prismaService = app.get(PrismaService); await prismaService.enableShutdownHooks(app); // Swagger Documentation const swaggerConfig = new DocumentBuilder() .setTitle('Lucky Wheel API') .setDescription('مستندات جامع وب‌سرویس سامانه گردونه شانس و قرعه‌کشی') .setVersion('1.0') .addBearerAuth( { type: 'http', scheme: 'bearer', bearerFormat: 'JWT', in: 'header' }, 'UserAuth', ) .addBearerAuth( { type: 'http', scheme: 'bearer', bearerFormat: 'JWT', in: 'header' }, 'AdminAuth', ) .build(); const document = SwaggerModule.createDocument(app, swaggerConfig); SwaggerModule.setup('api/docs', app, document); const port = configService.get('PORT', 3000); await app.listen(port); console.log(`Application is running on: http://localhost:${port}`); console.log(`Swagger documentation: http://localhost:${port}/api/docs`); } bootstrap();