import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { ValidationPipe } from '@nestjs/common'; import { useContainer } from 'class-validator'; import * as express from 'express'; import { ExpressAdapter, NestExpressApplication, } from '@nestjs/platform-express'; import { RawBodyRequest } from './types/raw-body-request'; import { validateEnvironment } from './common/validate-env'; async function bootstrap() { // Fail fast if critical env vars are missing validateEnvironment(); const server = express(); const captureRawBody = ( request: RawBodyRequest, _response: express.Response, buffer: Buffer, ) => { request.rawBody = buffer.toString('utf8'); }; server.use( express.json({ limit: '10mb', verify: captureRawBody, }), ); server.use( express.urlencoded({ extended: true, limit: '10mb', verify: captureRawBody, }), ); const app = await NestFactory.create( AppModule, new ExpressAdapter(server), { bodyParser: false, }, ); useContainer(app.select(AppModule), { fallbackOnErrors: true }); if ( process.env.ENVIRONMENT === 'development' || process.env.ENVIRONMENT === 'local' ) { const swagConfig = new DocumentBuilder() .setTitle('IndeeHub API') .setDescription('This is the API for the IndeeHub application') .setVersion('1.0') .build(); const document = SwaggerModule.createDocument(app, swagConfig); SwaggerModule.setup('api', app, document); } app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true })); if (process.env.ENVIRONMENT === 'production') { // Build CORS origin list from FRONTEND_URL + known domains const origins: string[] = [ 'https://indeehub.studio', 'https://www.indeehub.studio', 'https://app.indeehub.studio', 'https://bff.indeehub.studio', ]; if (process.env.FRONTEND_URL) { origins.push(process.env.FRONTEND_URL); } if (process.env.DOMAIN) { origins.push(`https://${process.env.DOMAIN}`); } app.enableCors({ origin: [...new Set(origins)], methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], credentials: true, }); } else { app.enableCors(); } await app.listen(process.env.PORT || 4000); } // eslint-disable-next-line unicorn/prefer-top-level-await bootstrap().catch(console.error);