thrilled-be-core
Version:
Core Express backend package with middleware, logging, security, and base application setup
105 lines (104 loc) • 4.55 kB
JavaScript
;
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;