mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
100 lines
3.8 KiB
TypeScript
100 lines
3.8 KiB
TypeScript
import "reflect-metadata";
|
|
import * as dotenv from "dotenv";
|
|
dotenv.config();
|
|
import { NestFactory } from "@nestjs/core";
|
|
import type { NestExpressApplication } from "@nestjs/platform-express";
|
|
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
|
|
import {
|
|
HttpExceptionFilter,
|
|
ResponseTransformInterceptor,
|
|
createValidationPipe,
|
|
} from "@edr/api-common";
|
|
|
|
import { AppModule } from "./app.module";
|
|
|
|
/**
|
|
* JSON body ceiling. Signing posts the signature AND the company stamp as
|
|
* base64 in one JSON body, and base64 inflates bytes by ~4/3 — a 10MB stamp is
|
|
* ~13.4MB on the wire. Express defaults to 100kb, which rejected any real stamp
|
|
* image with a 413 "request entity too large".
|
|
*/
|
|
const JSON_BODY_LIMIT = '20mb';
|
|
|
|
async function bootstrap() {
|
|
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
|
|
|
// Nest's own body-parser API, NOT `app.use(json(...))` from express: express
|
|
// is not a declared dependency of this app (it arrives under
|
|
// @nestjs/platform-express), so importing it directly resolved only through
|
|
// pnpm's hoisted dev store and died as MODULE_NOT_FOUND in the production
|
|
// image, where `pnpm deploy --prod` installs declared dependencies only.
|
|
// This also RECONFIGURES the default parsers rather than racing them.
|
|
app.useBodyParser('json', { limit: JSON_BODY_LIMIT });
|
|
app.useBodyParser('urlencoded', { limit: JSON_BODY_LIMIT, extended: true });
|
|
|
|
// 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",
|
|
// x-prefixed variants sent by the user-management / record-management
|
|
// frontend modules (same values, different naming convention)
|
|
"x-organization-unit-id",
|
|
"x-delegator-id",
|
|
"x-delegator-position-id",
|
|
"x-current-project-id",
|
|
"x-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();
|