@intuitionrobotics/thunderstorm
Version:
53 lines • 2.33 kB
JavaScript
import { Logger } from "@intuitionrobotics/ts-common";
import {} from "express";
import { parse } from "url";
import { composeApiError } from "./api-error.js";
import { apiDebug } from "./server-api.js";
import { HttpMethod } from "../../../shared/types.js";
const logger = new Logger("terminalErrorHandler");
/**
* Build the `HttpRequestData` shape (the same one `ServerApi.call()` assembles,
* server-api.ts:154-161) from a raw Express request, for the Storm error
* composer.
*/
function requestDataFrom(req) {
return {
method: (req.method ? req.method.toLowerCase() : HttpMethod.ALL),
originalUrl: req.path,
headers: req.headers,
url: req.url,
query: parse(req.url, true).query,
body: req.body
};
}
/**
* The single app-level error handler for raw (`handler()`-wrapped) endpoints.
* Register it LAST, after the router (see `ApiFunction`). It routes the error
* through the shared `composeApiError` pipeline, then writes the response with
* the same shape + `apiDebug.enabled` gating as `ApiResponse.serverError` /
* `ApiResponse.exception` (server-api.ts:428-440).
*
* Legacy `ServerApi` endpoints never reach here (they catch internally), so
* this is purely additive.
*/
export function terminalErrorHandler() {
return async (err, req, res, next) => {
// Headers already sent (stream/SSE) → can't rewrite the response; let
// Express's default finalize the (already-broken) connection.
if (res.headersSent)
return next(err);
const apiException = await composeApiError(err, requestDataFrom(req), logger);
const responseBody = apiException.responseBody;
if (!apiDebug.enabled)
delete responseBody.debugMessage;
if (apiException.responseCode === 500) {
const cause = apiException.cause;
const stack = cause ? cause.stack : apiException.stack;
const message = (cause ? cause.message : apiException.message) || "";
res.status(500).set("Content-Type", "text/plain").send(apiDebug.enabled && stack ? stack : message);
return;
}
res.status(apiException.responseCode).set("Content-Type", "application/json").send(JSON.stringify(responseBody, null, 2));
};
}
//# sourceMappingURL=app-middleware.js.map