Files
gridpilot.gg/apps/api/src/main.ts
2026-01-17 22:55:03 +01:00

107 lines
3.3 KiB
TypeScript

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();