Ich habe soweit automatisiert the Emails sortieren aber ich muss noch schauen was es fur bugs es gibt wenn die app online ist deswegen wurde ich mit diesen Commit die website veroffentlichen obwohjl es sein konnte das es noch nicht fertig ist und verkaufs bereit
107 lines
2.6 KiB
JavaScript
107 lines
2.6 KiB
JavaScript
/**
|
|
* Global Error Handler Middleware
|
|
* Catches all errors and returns consistent JSON responses
|
|
*/
|
|
|
|
export class AppError extends Error {
|
|
constructor(message, statusCode = 500, code = 'INTERNAL_ERROR') {
|
|
super(message)
|
|
this.statusCode = statusCode
|
|
this.code = code
|
|
this.isOperational = true
|
|
Error.captureStackTrace(this, this.constructor)
|
|
}
|
|
}
|
|
|
|
export class ValidationError extends AppError {
|
|
constructor(message, fields = {}) {
|
|
super(message, 400, 'VALIDATION_ERROR')
|
|
this.fields = fields
|
|
}
|
|
}
|
|
|
|
export class AuthenticationError extends AppError {
|
|
constructor(message = 'Nicht authentifiziert') {
|
|
super(message, 401, 'AUTHENTICATION_ERROR')
|
|
}
|
|
}
|
|
|
|
export class AuthorizationError extends AppError {
|
|
constructor(message = 'Keine Berechtigung') {
|
|
super(message, 403, 'AUTHORIZATION_ERROR')
|
|
}
|
|
}
|
|
|
|
export class NotFoundError extends AppError {
|
|
constructor(resource = 'Ressource') {
|
|
super(`${resource} nicht gefunden`, 404, 'NOT_FOUND')
|
|
}
|
|
}
|
|
|
|
export class RateLimitError extends AppError {
|
|
constructor(message = 'Zu viele Anfragen') {
|
|
super(message, 429, 'RATE_LIMIT_EXCEEDED')
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error handler middleware
|
|
*/
|
|
export function errorHandler(err, req, res, next) {
|
|
// Log error
|
|
console.error(`[ERROR] ${new Date().toISOString()}`, {
|
|
method: req.method,
|
|
path: req.path,
|
|
error: err.message,
|
|
stack: process.env.NODE_ENV === 'development' ? err.stack : undefined,
|
|
})
|
|
|
|
// Default error values
|
|
let statusCode = err.statusCode || 500
|
|
let code = err.code || 'INTERNAL_ERROR'
|
|
let message = err.message || 'Ein Fehler ist aufgetreten'
|
|
|
|
// Handle specific error types
|
|
if (err.name === 'ValidationError') {
|
|
statusCode = 400
|
|
code = 'VALIDATION_ERROR'
|
|
}
|
|
|
|
if (err.name === 'JsonWebTokenError') {
|
|
statusCode = 401
|
|
code = 'INVALID_TOKEN'
|
|
message = 'Ungültiger Token'
|
|
}
|
|
|
|
if (err.name === 'TokenExpiredError') {
|
|
statusCode = 401
|
|
code = 'TOKEN_EXPIRED'
|
|
message = 'Token abgelaufen'
|
|
}
|
|
|
|
// Don't expose internal errors in production
|
|
if (!err.isOperational && process.env.NODE_ENV === 'production') {
|
|
message = 'Ein interner Fehler ist aufgetreten'
|
|
}
|
|
|
|
// Send response
|
|
res.status(statusCode).json({
|
|
success: false,
|
|
error: {
|
|
code,
|
|
message,
|
|
...(err.fields && { fields: err.fields }),
|
|
...(process.env.NODE_ENV === 'development' && { stack: err.stack }),
|
|
},
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Async handler wrapper to catch errors in async routes
|
|
*/
|
|
export function asyncHandler(fn) {
|
|
return (req, res, next) => {
|
|
Promise.resolve(fn(req, res, next)).catch(next)
|
|
}
|
|
}
|