import { Request, Response, NextFunction } from 'express'; import { GenerateImageResponse } from '../types/api'; /** * Global error handler for the Express application */ export const errorHandler = ( error: Error, req: Request, res: Response, next: NextFunction ) => { const timestamp = new Date().toISOString(); const requestId = req.requestId || 'unknown'; // Log the error console.error(`[${timestamp}] [${requestId}] ERROR:`, { message: error.message, stack: error.stack, path: req.path, method: req.method, body: req.body, query: req.query }); // Don't send error response if headers already sent if (res.headersSent) { return next(error); } // Determine error type and status code let statusCode = 500; let errorMessage = 'Internal server error'; let errorType = 'INTERNAL_ERROR'; if (error.name === 'ValidationError') { statusCode = 400; errorMessage = error.message; errorType = 'VALIDATION_ERROR'; } else if (error.message.includes('API key') || error.message.includes('authentication')) { statusCode = 401; errorMessage = 'Authentication failed'; errorType = 'AUTH_ERROR'; } else if (error.message.includes('not found') || error.message.includes('404')) { statusCode = 404; errorMessage = 'Resource not found'; errorType = 'NOT_FOUND'; } else if (error.message.includes('timeout') || error.message.includes('503')) { statusCode = 503; errorMessage = 'Service temporarily unavailable'; errorType = 'SERVICE_UNAVAILABLE'; } else if (error.message.includes('overloaded') || error.message.includes('rate limit')) { statusCode = 429; errorMessage = 'Service overloaded, please try again later'; errorType = 'RATE_LIMITED'; } // Create error response const errorResponse: GenerateImageResponse = { success: false, message: 'Request failed', error: errorMessage }; // Add additional debug info in development if (process.env.NODE_ENV === 'development') { (errorResponse as any).debug = { originalError: error.message, errorType, requestId, timestamp }; } console.log(`[${timestamp}] [${requestId}] Sending error response: ${statusCode} - ${errorMessage}`); res.status(statusCode).json(errorResponse); }; /** * 404 handler for unmatched routes */ export const notFoundHandler = (req: Request, res: Response) => { const timestamp = new Date().toISOString(); const requestId = req.requestId || 'unknown'; console.log(`[${timestamp}] [${requestId}] 404 - Route not found: ${req.method} ${req.path}`); const notFoundResponse: GenerateImageResponse = { success: false, message: 'Route not found', error: `The requested endpoint ${req.method} ${req.path} does not exist` }; res.status(404).json(notFoundResponse); }; /** * Async error wrapper to catch errors in async route handlers */ export const asyncHandler = (fn: Function) => (req: Request, res: Response, next: NextFunction) => { Promise.resolve(fn(req, res, next)).catch(next); };