import 'reflect-metadata'; import { ValidationPipe } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { writeFileSync } from 'fs'; import { join } from 'path'; import { AppModule } from './app.module'; import { AuthenticationGuard } from './domain/auth/AuthenticationGuard'; import { AuthorizationGuard } from './domain/auth/AuthorizationGuard'; import { FeatureAvailabilityGuard } from './domain/policy/FeatureAvailabilityGuard'; import { getGenerateOpenapi } from './env'; async function bootstrap() { const generateOpenapi = getGenerateOpenapi(); console.log('🚀 Starting GridPilot API...'); const app = await NestFactory.create(AppModule, { logger: ['error', 'warn', 'log'], // Clean logging abortOnError: false, }); // CORS for website integration app.enableCors({ credentials: true, origin: (origin, callback) => { callback(null, origin || false); }, }); // Validation app.useGlobalPipes( new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true, transform: true, }), ); try { const authGuard = app.get(AuthenticationGuard); const authzGuard = app.get(AuthorizationGuard); const featureGuard = app.get(FeatureAvailabilityGuard); app.useGlobalGuards(authGuard, authzGuard, featureGuard); } catch (error) { console.error('Failed to register guards:', error); throw error; } // Swagger const config = new DocumentBuilder() .setTitle('GridPilot API') .setDescription('GridPilot API documentation') .setVersion('1.0') .addTag('dashboard', 'Dashboard endpoints') .addTag('races', 'Race management endpoints') .addTag('leagues', 'League management endpoints') .addTag('teams', 'Team management endpoints') .addTag('drivers', 'Driver management endpoints') .addTag('sponsors', 'Sponsor management endpoints') .addTag('payments', 'Payment and billing endpoints') .addTag('media', 'Media and file management endpoints') .addTag('analytics', 'Analytics and reporting endpoints') .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api/docs', app, document); // OpenAPI export if (generateOpenapi) { const outputPath = join(__dirname, '../openapi.json'); writeFileSync(outputPath, JSON.stringify(document, null, 2)); console.log(`✅ OpenAPI spec generated at: ${outputPath}`); await app.close(); process.exit(0); } // Start server try { const port = process.env.PORT || 3000; await app.listen(port); console.log(`✅ API Server started successfully on port ${port}`); console.log(`📚 Swagger docs: http://localhost:${port}/api/docs`); } catch (error: unknown) { console.error('❌ Failed to start API server:', error instanceof Error ? error.message : 'Unknown error'); process.exit(1); } } // Handle uncaught errors process.on('uncaughtException', (error) => { console.error('🚨 Uncaught Exception:', error.stack ?? error.message); process.exit(1); }); process.on('unhandledRejection', (reason: unknown) => { if (reason instanceof Error) { console.error('🚨 Unhandled Rejection:', reason.stack ?? reason.message); } else { console.error('🚨 Unhandled Rejection:', reason); } process.exit(1); }); bootstrap();