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); }; };