UNPKG

thrilled-be-core

Version:

Core Express backend package with middleware, logging, security, and base application setup

105 lines (104 loc) 4.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ErrorMiddleware = void 0; const types_1 = require("../types"); const responseFormatter_1 = require("../plugins/responseFormatter"); class ErrorMiddleware { logger; constructor(logger) { this.logger = logger; } /** * Global error handler middleware */ handle() { return (error, req, res, // eslint-disable-next-line @typescript-eslint/no-unused-vars _next) => { try { // Handle both HttpException class and legacy error objects with statusCode const statusCode = 'statusCode' in error ? error.statusCode : undefined; const status = error.status || statusCode || types_1.HttpStatusCodes.INTERNAL_SERVER_ERROR; const message = error.message || 'Something went wrong'; const requestId = req.requestId; // Log the error with request context this.logger.error(error, { method: req.method, url: req.url, requestId, userAgent: req.get('User-Agent'), ip: req.ip, }); // Don't expose internal errors in production const responseMessage = status === types_1.HttpStatusCodes.INTERNAL_SERVER_ERROR && process.env.NODE_ENV === 'production' ? 'Internal server error' : message; // Create meta data for development debugging const meta = { ...(requestId && { requestId }), ...(process.env.NODE_ENV === 'development' && { stack: error.stack, }), }; // Create error objects for validation errors const errors = requestId || (process.env.NODE_ENV === 'development' && error.stack) ? [ { message: responseMessage, ...(requestId && { field: 'requestId' }), }, ] : undefined; switch (status) { case types_1.HttpStatusCodes.BAD_REQUEST: responseFormatter_1.apiResponse.custom(res, status, responseMessage, undefined, meta, errors); break; case types_1.HttpStatusCodes.UNAUTHORIZED: responseFormatter_1.apiResponse.custom(res, status, responseMessage, undefined, meta); break; case types_1.HttpStatusCodes.FORBIDDEN: responseFormatter_1.apiResponse.custom(res, status, responseMessage, undefined, meta); break; case types_1.HttpStatusCodes.NOT_FOUND: responseFormatter_1.apiResponse.custom(res, status, responseMessage, undefined, meta); break; case types_1.HttpStatusCodes.CONFLICT: responseFormatter_1.apiResponse.custom(res, status, responseMessage, undefined, meta); break; case types_1.HttpStatusCodes.UNPROCESSABLE_ENTITY: responseFormatter_1.apiResponse.custom(res, status, responseMessage, undefined, meta, errors); break; default: responseFormatter_1.apiResponse.custom(res, status, responseMessage, undefined, meta); } } catch (err) { // Fallback error handling this.logger.error(err, { context: 'ErrorMiddleware.handle' }); res.status(500).json({ success: false, message: 'Internal server error', statusCode: 500, }); } }; } /** * 404 Not Found handler */ notFound() { return (req, res) => { const requestId = req.requestId; res.status(404).json({ success: false, message: `Route ${req.method} ${req.url} not found`, statusCode: 404, ...(requestId && { requestId }), }); }; } } exports.ErrorMiddleware = ErrorMiddleware;