import { randomUUID } from "node:crypto"; import type { HttpErrorResponseDTO } from "@metis/core/common"; import { registerCoreRoutes } from "@metis/core/module"; import type { Application, ErrorRequestHandler, RequestHandler } from "express"; import express from "express"; import helmet from "helmet"; import type { HttpLogger } from "./infrastructure/http/http-logger"; import { logHttpRequest } from "./infrastructure/http/http-logger"; export function createApp( logger: HttpLogger = logHttpRequest, identity?: { middleware: RequestHandler; register: (app: Application) => void } ) { const app = express(); app.disable("x-powered-by"); app.use(helmet()); app.use((request, response, next) => { const requestId = randomUUID(); const startedAt = performance.now(); response.setHeader("x-request-id", requestId); response.setHeader("cache-control", "no-store"); response.once("finish", () => { logger({ event: "http_request", requestId, method: request.method, statusCode: response.statusCode, durationMs: Math.round((performance.now() - startedAt) * 100) / 100, }); }); next(); }); app.use(express.json({ limit: "64kb" })); if (identity) { app.use(identity.middleware); identity.register(app); } registerCoreRoutes(app); app.use((_request, response) => { const error: HttpErrorResponseDTO = { code: "NOT_FOUND", requestId: response.getHeader("x-request-id")?.toString() ?? "", }; response.status(404).json(error); }); const errorHandler: ErrorRequestHandler = (_error: unknown, _request, response, next) => { if (response.headersSent) { next(_error); return; } const error: HttpErrorResponseDTO = { code: "INTERNAL_ERROR", requestId: response.getHeader("x-request-id")?.toString() ?? "", }; response.status(500).json(error); }; app.use(errorHandler); return app; }