/** * Zentrale Fehlerbehandlung für die Anwendung */ class ErrorHandler { /** * Erstellt eine standardisierte Fehlerantwort * @param {Object} res - Express Response Objekt * @param {number} statusCode - HTTP Status Code * @param {string} message - Fehlermeldung * @param {Object} details - Zusätzliche Fehlerdetails (optional) */ static errorResponse(res, statusCode, message, details = null) { const error = { success: false, message, timestamp: new Date().toISOString() }; if (details) { error.details = details; } console.error(`[${statusCode}] ${message}`, details ? details : ''); return res.status(statusCode).json(error); } /** * Erstellt eine erfolgreiche Antwort * @param {Object} res - Express Response Objekt * @param {Object} data - Antwortdaten * @param {string} message - Erfolgsmeldung * @param {number} statusCode - HTTP Status Code (default: 200) */ static successResponse(res, data, message = 'Erfolgreich', statusCode = 200) { const response = { success: true, message, data, timestamp: new Date().toISOString() }; return res.status(statusCode).json(response); } /** * Wrapper für async Controller-Funktionen mit automatischer Fehlerbehandlung * @param {Function} fn - Async Controller-Funktion * @returns {Function} - Wrapped Controller-Funktion */ static asyncHandler(fn) { return (req, res, next) => { Promise.resolve(fn(req, res, next)).catch((error) => { console.error('Unhandled error in async handler:', error); this.errorResponse(res, 500, 'Ein unerwarteter Fehler ist aufgetreten', { error: error.message, stack: process.env.NODE_ENV === 'development' ? error.stack : undefined }); }); }; } /** * Behandelt Sequelize-Validierungsfehler * @param {Object} error - Sequelize Error * @returns {Object} - Standardisierte Fehlerantwort */ static handleSequelizeError(error) { if (error.name === 'SequelizeValidationError') { const validationErrors = error.errors.map(err => ({ field: err.path, message: err.message, value: err.value })); return { statusCode: 400, message: 'Validierungsfehler', details: { validationErrors } }; } if (error.name === 'SequelizeUniqueConstraintError') { return { statusCode: 409, message: 'Eindeutigkeitsverletzung', details: { field: error.errors[0]?.path } }; } if (error.name === 'SequelizeForeignKeyConstraintError') { return { statusCode: 400, message: 'Referenzfehler', details: { field: error.fields[0] } }; } if (error.name === 'SequelizeDatabaseError') { return { statusCode: 500, message: 'Datenbankfehler', details: { original: error.original?.message } }; } return { statusCode: 500, message: 'Datenbankfehler', details: { error: error.message } }; } /** * Behandelt JWT-Fehler * @param {Object} error - JWT Error * @returns {Object} - Standardisierte Fehlerantwort */ static handleJWTError(error) { if (error.name === 'JsonWebTokenError') { return { statusCode: 401, message: 'Ungültiger Token' }; } if (error.name === 'TokenExpiredError') { return { statusCode: 401, message: 'Token abgelaufen' }; } return { statusCode: 401, message: 'Authentifizierungsfehler' }; } } module.exports = ErrorHandler;