Spaces:
Paused
Paused
File size: 3,756 Bytes
c904036 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | /**
* Custom Error Classes for CampVerse Backend
* Provides standardized error handling with proper HTTP status codes
*/
class AppError extends Error {
constructor(message, statusCode, isOperational = true) {
super(message);
this.statusCode = statusCode;
this.isOperational = isOperational;
this.timestamp = new Date().toISOString();
Error.captureStackTrace(this, this.constructor);
}
}
class ValidationError extends AppError {
constructor(message, details = null) {
super(message, 400);
this.name = 'ValidationError';
this.details = details;
}
}
class AuthenticationError extends AppError {
constructor(message = 'Authentication failed') {
super(message, 401);
this.name = 'AuthenticationError';
}
}
class AuthorizationError extends AppError {
constructor(message = 'Insufficient permissions') {
super(message, 403);
this.name = 'AuthorizationError';
}
}
class NotFoundError extends AppError {
constructor(resource = 'Resource') {
super(`${resource} not found`, 404);
this.name = 'NotFoundError';
}
}
class ConflictError extends AppError {
constructor(message = 'Resource conflict') {
super(message, 409);
this.name = 'ConflictError';
}
}
class RateLimitError extends AppError {
constructor(message = 'Too many requests') {
super(message, 429);
this.name = 'RateLimitError';
}
}
class DatabaseError extends AppError {
constructor(message = 'Database operation failed', originalError = null) {
super(message, 500);
this.name = 'DatabaseError';
this.originalError = originalError;
}
}
class ExternalServiceError extends AppError {
constructor(service, message = 'External service unavailable', statusCode = 503) {
super(`${service}: ${message}`, statusCode);
this.name = 'ExternalServiceError';
this.service = service;
}
}
class BusinessLogicError extends AppError {
constructor(message, statusCode = 422) {
super(message, statusCode);
this.name = 'BusinessLogicError';
}
}
// Error factory functions for common scenarios
const createValidationError = (field, value, constraint) => {
return new ValidationError(`Invalid ${field}: ${constraint}`, {
field,
value,
constraint
});
};
const createNotFoundError = (resource, id = null) => {
const message = id ? `${resource} with ID ${id} not found` : `${resource} not found`;
return new NotFoundError(message);
};
const createConflictError = (resource, field, value) => {
return new ConflictError(`${resource} with ${field} '${value}' already exists`);
};
const createAuthError = (reason = 'Invalid credentials') => {
return new AuthenticationError(reason);
};
const createPermissionError = (action, resource) => {
return new AuthorizationError(`Insufficient permissions to ${action} ${resource}`);
};
// Error type checking utilities
const isOperationalError = (error) => {
return error instanceof AppError && error.isOperational;
};
const isDatabaseError = (error) => {
return error instanceof DatabaseError ||
error.name === 'MongoError' ||
error.name === 'ValidationError' ||
error.name === 'CastError';
};
const isValidationError = (error) => {
return error instanceof ValidationError ||
error.name === 'ValidationError';
};
module.exports = {
AppError,
ValidationError,
AuthenticationError,
AuthorizationError,
NotFoundError,
ConflictError,
RateLimitError,
DatabaseError,
ExternalServiceError,
BusinessLogicError,
// Factory functions
createValidationError,
createNotFoundError,
createConflictError,
createAuthError,
createPermissionError,
// Utility functions
isOperationalError,
isDatabaseError,
isValidationError
}; |