- Full grant strategy framework for renewable energy & green hydrogen - AI-powered grant studio, partner outreach, financial modeling - Umami analytics with data-performance tracking - Live Degelas metrics connected to solar.degelas.be - Trilingual (EN/FR/AR) with i18n support - Dockerized with Nginx frontend + Express API proxy
52 lines
1.2 KiB
TypeScript
52 lines
1.2 KiB
TypeScript
import type { Request, Response, NextFunction } from "express";
|
|
import createHttpError from "http-errors";
|
|
import logger from "./logger";
|
|
|
|
/**
|
|
* Global error handler middleware.
|
|
* - Logs errors with full context
|
|
* - Returns sanitized error responses in production
|
|
* - Returns detailed errors in development
|
|
*/
|
|
|
|
export function errorHandler(err: any, req: Request, res: Response, next: NextFunction) {
|
|
// Log the error
|
|
logger.error(
|
|
{
|
|
err,
|
|
path: req.path,
|
|
method: req.method,
|
|
body: req.body,
|
|
},
|
|
"request error"
|
|
);
|
|
|
|
// Determine status code
|
|
const status = err.status || err.statusCode || 500;
|
|
|
|
// Build response
|
|
const response: any = {
|
|
ok: false,
|
|
error: err.message || "Internal server error",
|
|
};
|
|
|
|
// In development, include stack trace
|
|
if (process.env.NODE_ENV !== "production") {
|
|
response.stack = err.stack;
|
|
response.details = err.details;
|
|
}
|
|
|
|
// Add request ID if available
|
|
const reqId = res.getHeader("X-Request-ID");
|
|
if (reqId) {
|
|
response.requestId = reqId;
|
|
}
|
|
|
|
res.status(status).json(response);
|
|
}
|
|
|
|
// 404 handler
|
|
export function notFoundHandler(req: Request, res: Response, next: NextFunction) {
|
|
next(createHttpError(404, `Not found: ${req.method} ${req.path}`));
|
|
}
|