import "reflect-metadata"; import * as dotenv from "dotenv"; dotenv.config(); import { NestFactory } from "@nestjs/core"; import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger"; import { HttpExceptionFilter, ResponseTransformInterceptor, createValidationPipe, } from "@edr/api-common"; import { AppModule } from "./app.module"; async function bootstrap() { const app = await NestFactory.create(AppModule); // Dev CORS: reflect any localhost origin and allow credentials so the // freight portal (5173), passenger portal (5174), backoffices (5183/5184) // and any other dev port can call the API with cookies + Authorization. // For production, restrict `origin` to known FQDNs. app.enableCors({ origin: true, // reflect request origin credentials: true, methods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE", "OPTIONS"], allowedHeaders: [ "Content-Type", "Accept", "Authorization", "X-Requested-With", // IAM context headers required by @tria-plc/api-common's JwtGuard "organization-unit-id", "delegator-position-id", "current-project-id", "current-position-id", ], exposedHeaders: ["Content-Disposition"], maxAge: 86400, // cache preflight for 24h to cut chatter in dev }); // /callback stays un-prefixed: it's the Fayda OAuth redirect_uri ack endpoint. app.setGlobalPrefix("api", { exclude: ["callback"] }); // enableImplicitConversion is OFF: class-transformer's implicit boolean // coercion turns any non-empty multipart/form-data string (including the // literal "false") into `true`, silently corrupting flags like isHazardous // and isGovernment. With it off, only explicit @Transform/@Type decorators // coerce values — every numeric/boolean DTO field in this API already has one. app.useGlobalPipes( createValidationPipe({ transformOptions: { enableImplicitConversion: false }, }), ); app.useGlobalFilters(new HttpExceptionFilter()); app.useGlobalInterceptors(new ResponseTransformInterceptor()); const config = new DocumentBuilder() .setTitle("EDR Freight API") .setDescription("API for the EDR Freight Management application") .setVersion("0.1.0") .addBearerAuth() .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup("api/docs", app, document); const port = parseInt(process.env.PORT ?? "3001", 10); // await app.listen(port, "0.0.0.0"); await app.listen( port) // eslint-disable-next-line no-console console.log(`[freight-api] listening on port ${port}`); } bootstrap();