70 lines
1.7 KiB
TypeScript
70 lines
1.7 KiB
TypeScript
import { Request, Response, NextFunction } from 'express';
|
|
import logger from './logger';
|
|
import { ResponseHandler } from './responseHandler';
|
|
|
|
export class AppError extends Error {
|
|
public statusCode: number;
|
|
public isOperational: boolean;
|
|
|
|
constructor(message: string, statusCode: number = 500) {
|
|
super(message);
|
|
this.statusCode = statusCode;
|
|
this.isOperational = true;
|
|
|
|
Error.captureStackTrace(this, this.constructor);
|
|
}
|
|
}
|
|
|
|
export const errorHandler = (
|
|
error: Error,
|
|
req: Request,
|
|
res: Response,
|
|
_next: NextFunction
|
|
): void => {
|
|
let statusCode = 500;
|
|
let message = 'Internal Server Error';
|
|
|
|
if (error instanceof AppError) {
|
|
statusCode = error.statusCode;
|
|
message = error.message;
|
|
} else if (error.name === 'ValidationError') {
|
|
statusCode = 400;
|
|
message = 'Validation Error';
|
|
} else if (error.name === 'UnauthorizedError') {
|
|
statusCode = 401;
|
|
message = 'Unauthorized';
|
|
} else if (error.name === 'CastError') {
|
|
statusCode = 400;
|
|
message = 'Invalid ID format';
|
|
} else if (error.name === 'MongoError' && (error as any).code === 11000) {
|
|
statusCode = 400;
|
|
message = 'Duplicate field value';
|
|
}
|
|
|
|
logger.error('Error occurred:', {
|
|
error: error.message,
|
|
stack: error.stack,
|
|
statusCode,
|
|
url: req.url,
|
|
method: req.method,
|
|
ip: req.ip,
|
|
});
|
|
|
|
ResponseHandler.error(res, message, statusCode, error.message);
|
|
};
|
|
|
|
export const notFoundHandler = (
|
|
req: Request,
|
|
_res: Response,
|
|
next: NextFunction
|
|
): void => {
|
|
const error = new AppError(`Route ${req.originalUrl} not found`, 404);
|
|
next(error);
|
|
};
|
|
|
|
export const asyncHandler = (fn: Function) => {
|
|
return (req: Request, res: Response, next: NextFunction) => {
|
|
Promise.resolve(fn(req, res, next)).catch(next);
|
|
};
|
|
};
|