Spaces:
Configuration error
Configuration error
| import { Request, Response, NextFunction } from 'express' | |
| import { Prisma } from '@prisma/client' | |
| export interface AppError extends Error { | |
| statusCode?: number | |
| code?: string | |
| } | |
| export const errorHandler = ( | |
| error: AppError, | |
| req: Request, | |
| res: Response, | |
| next: NextFunction | |
| ) => { | |
| console.error('Error:', error) | |
| // Default error | |
| let statusCode = error.statusCode || 500 | |
| let message = error.message || 'Internal server error' | |
| let code = error.code || 'INTERNAL_ERROR' | |
| // Prisma errors | |
| if (error instanceof Prisma.PrismaClientKnownRequestError) { | |
| switch (error.code) { | |
| case 'P2002': | |
| statusCode = 409 | |
| message = 'Resource already exists' | |
| code = 'DUPLICATE_ERROR' | |
| break | |
| case 'P2025': | |
| statusCode = 404 | |
| message = 'Resource not found' | |
| code = 'NOT_FOUND' | |
| break | |
| case 'P2003': | |
| statusCode = 400 | |
| message = 'Invalid reference' | |
| code = 'INVALID_REFERENCE' | |
| break | |
| default: | |
| statusCode = 400 | |
| message = 'Database error' | |
| code = 'DATABASE_ERROR' | |
| } | |
| } | |
| // Validation errors | |
| if (error.name === 'ValidationError') { | |
| statusCode = 400 | |
| code = 'VALIDATION_ERROR' | |
| } | |
| // JWT errors | |
| if (error.name === 'JsonWebTokenError') { | |
| statusCode = 401 | |
| message = 'Invalid token' | |
| code = 'INVALID_TOKEN' | |
| } | |
| if (error.name === 'TokenExpiredError') { | |
| statusCode = 401 | |
| message = 'Token expired' | |
| code = 'TOKEN_EXPIRED' | |
| } | |
| // Multer errors (file upload) | |
| if (error.code === 'LIMIT_FILE_SIZE') { | |
| statusCode = 413 | |
| message = 'File too large' | |
| code = 'FILE_TOO_LARGE' | |
| } | |
| if (error.code === 'LIMIT_FILE_COUNT') { | |
| statusCode = 413 | |
| message = 'Too many files' | |
| code = 'TOO_MANY_FILES' | |
| } | |
| // Don't expose internal errors in production | |
| if (process.env.NODE_ENV === 'production' && statusCode === 500) { | |
| message = 'Internal server error' | |
| } | |
| res.status(statusCode).json({ | |
| success: false, | |
| error: message, | |
| code, | |
| ...(process.env.NODE_ENV === 'development' && { stack: error.stack }) | |
| }) | |
| } | |
| export const notFoundHandler = (req: Request, res: Response) => { | |
| res.status(404).json({ | |
| success: false, | |
| error: 'Route not found', | |
| code: 'NOT_FOUND' | |
| }) | |
| } | |
| export const asyncHandler = (fn: (req: Request, res: Response, next: NextFunction) => Promise<any>) => { | |
| return (req: Request, res: Response, next: NextFunction) => { | |
| Promise.resolve(fn(req, res, next)).catch(next) | |
| } | |
| } | |