import { NestFactory } from '@nestjs/core'; import { ValidationPipe } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import helmet from 'helmet'; import { AppModule } from './app.module'; import { AllExceptionsFilter } from './common/all-exceptions.filter'; async function bootstrap() { const app = await NestFactory.create(AppModule); const configService = app.get(ConfigService); app.useGlobalFilters(new AllExceptionsFilter()); // Security app.use(helmet()); // CORS — allow the web frontend origin (from NEXT_PUBLIC_APP_URL) + localhost for dev const appUrl = configService.get('NEXT_PUBLIC_APP_URL'); const allowedOrigins = [ ...new Set( [appUrl, 'http://localhost:3080', 'http://localhost:3000'].filter(Boolean) as string[], ), ]; console.log('CORS allowed origins:', allowedOrigins); app.enableCors({ origin: allowedOrigins, credentials: true, }); // Global prefix app.setGlobalPrefix('api'); // Validation app.useGlobalPipes( new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true, transform: true, transformOptions: { enableImplicitConversion: true, }, }) ); // Swagger if (configService.get('NODE_ENV') !== 'production') { const config = new DocumentBuilder() .setTitle('CourseCraft API') .setDescription('AI-powered course creation platform API') .setVersion('1.0') .addBearerAuth() .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('docs', app, document); } const port = configService.get('PORT') || 3125; await app.listen(port); console.log(`🚀 API is running on: http://localhost:${port}/api`); console.log(`📚 Swagger docs: http://localhost:${port}/docs`); } bootstrap();