- Add comprehensive error handling to Post model with ValidationError, NotFoundError - Fix Post model toJSON method duplicate type field bug - Update Post test suite with proper mocking for all CouchDB service methods - All 23 Post model tests now passing - Complete standardized error handling implementation for User, Report, and Post models - Add modelErrors utility with structured error classes and logging 🤖 Generated with AI Assistant Co-Authored-By: AI Assistant <noreply@ai-assistant.com>
145 lines
3.7 KiB
JavaScript
145 lines
3.7 KiB
JavaScript
/**
|
|
* Standardized error classes and utilities for model operations
|
|
* Provides consistent error handling across all models
|
|
*/
|
|
|
|
class ModelError extends Error {
|
|
constructor(message, code = 'MODEL_ERROR', context = {}) {
|
|
super(message);
|
|
this.name = 'ModelError';
|
|
this.code = code;
|
|
this.context = context;
|
|
this.timestamp = new Date().toISOString();
|
|
}
|
|
|
|
toJSON() {
|
|
return {
|
|
name: this.name,
|
|
message: this.message,
|
|
code: this.code,
|
|
context: this.context,
|
|
timestamp: this.timestamp
|
|
};
|
|
}
|
|
}
|
|
|
|
class ValidationError extends ModelError {
|
|
constructor(message, field = null, value = null) {
|
|
super(message, 'VALIDATION_ERROR', { field, value });
|
|
this.name = 'ValidationError';
|
|
}
|
|
}
|
|
|
|
class NotFoundError extends ModelError {
|
|
constructor(resource, id = null) {
|
|
const message = id ? `${resource} with id '${id}' not found` : `${resource} not found`;
|
|
super(message, 'NOT_FOUND', { resource, id });
|
|
this.name = 'NotFoundError';
|
|
}
|
|
}
|
|
|
|
class DatabaseError extends ModelError {
|
|
constructor(operation, originalError) {
|
|
const message = `Database operation '${operation}' failed: ${originalError.message}`;
|
|
super(message, 'DATABASE_ERROR', {
|
|
operation,
|
|
originalError: originalError.message,
|
|
stack: originalError.stack
|
|
});
|
|
this.name = 'DatabaseError';
|
|
}
|
|
}
|
|
|
|
class DuplicateError extends ModelError {
|
|
constructor(resource, field, value) {
|
|
const message = `${resource} with ${field} '${value}' already exists`;
|
|
super(message, 'DUPLICATE_ERROR', { resource, field, value });
|
|
this.name = 'DuplicateError';
|
|
}
|
|
}
|
|
|
|
class AuthenticationError extends ModelError {
|
|
constructor(message = 'Authentication failed') {
|
|
super(message, 'AUTHENTICATION_ERROR');
|
|
this.name = 'AuthenticationError';
|
|
}
|
|
}
|
|
|
|
class AuthorizationError extends ModelError {
|
|
constructor(action = 'perform this action') {
|
|
super(`Not authorized to ${action}`, 'AUTHORIZATION_ERROR');
|
|
this.name = 'AuthorizationError';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error logging utility with context
|
|
*/
|
|
function logModelError(error, operation, model, additionalContext = {}) {
|
|
const errorInfo = {
|
|
timestamp: new Date().toISOString(),
|
|
model,
|
|
operation,
|
|
error: {
|
|
name: error.name,
|
|
message: error.message,
|
|
code: error.code,
|
|
context: error.context
|
|
},
|
|
...additionalContext
|
|
};
|
|
|
|
console.error(`[MODEL_ERROR] ${model}.${operation}:`, errorInfo);
|
|
|
|
// In production, you might want to send this to a logging service
|
|
if (process.env.NODE_ENV === 'production') {
|
|
// Production logging logic here
|
|
console.error('Production error logged:', JSON.stringify(errorInfo, null, 2));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wrapper for async model operations with consistent error handling
|
|
*/
|
|
async function withErrorHandling(operation, errorContext) {
|
|
try {
|
|
return await operation();
|
|
} catch (error) {
|
|
// Always log the error for debugging
|
|
logModelError(error, errorContext.operation, errorContext.model, errorContext);
|
|
|
|
// If it's already one of our custom errors, just rethrow
|
|
if (error instanceof ModelError) {
|
|
throw error;
|
|
}
|
|
|
|
// For backward compatibility, rethrow the original error
|
|
// This ensures existing tests and code continue to work
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create error context object for consistent logging
|
|
*/
|
|
function createErrorContext(model, operation, additional = {}) {
|
|
return {
|
|
model,
|
|
operation,
|
|
timestamp: new Date().toISOString(),
|
|
...additional
|
|
};
|
|
}
|
|
|
|
module.exports = {
|
|
ModelError,
|
|
ValidationError,
|
|
NotFoundError,
|
|
DatabaseError,
|
|
DuplicateError,
|
|
AuthenticationError,
|
|
AuthorizationError,
|
|
logModelError,
|
|
withErrorHandling,
|
|
createErrorContext
|
|
}; |