BillTracker/middleware/errorFormatter.js

105 lines
2.8 KiB
JavaScript
Raw Normal View History

2026-05-09 13:03:36 -05:00
/**
* Centralized Error Formatter Middleware
*
* Standard error response format:
* {
* "error": "ValidationError",
* "message": "Human-readable description",
* "field": "optional-field-name",
* "code": "machine-readable-code"
* }
*/
const { ValidationError, formatError } = require('../utils/apiError');
/**
* Extract field name from various validation error patterns
*/
function extractFieldFromError(message) {
if (!message) return null;
// Patterns like "field must be ..." or "field is ..."
const fieldMatch = message.match(/^(\w+)\s+(?:must be|is|are)\s+/i);
if (fieldMatch) return fieldMatch[1];
// Patterns like "year must be..." or "month must be..."
const yearMonthMatch = message.match(/^(year|month|due_day|interest_rate|actual_amount|start_year|start_month|end_year|end_month)\s+must\b/i);
if (yearMonthMatch) return yearMonthMatch[1];
// Patterns like "name is required"
const requiredMatch = message.match(/^(username|password|name|bill_id|category_id|due_day)\s+(?:is|are)\s+required/i);
if (requiredMatch) return requiredMatch[1];
return null;
}
/**
* Convert a plain error message/string into a standardized error object
*/
function standardizeError(message, code = 'VALIDATION_ERROR', fieldOverride = null) {
const field = fieldOverride || extractFieldFromError(message);
return {
error: code,
message: typeof message === 'string' ? message : String(message),
field: field || null,
code: code
};
}
/**
* Express middleware that ensures all error responses follow standard format
*/
function errorFormatter(req, res, next) {
const originalJson = res.json;
res.json = function(data) {
// If data is an error object (has error property), standardize it
if (data && typeof data === 'object' && data.error && !data.success) {
const standardized = standardizeError(data.error, data.error || 'ERROR', data.field);
return originalJson.call(this, standardized);
}
return originalJson.call(this, data);
};
next();
}
/**
* Helper to format validation errors with proper field extraction
*/
function formatValidationError(message, field) {
return standardizeError(message, 'VALIDATION_ERROR', field);
}
/**
* Helper to format not found errors
*/
function formatNotFoundError(message, field) {
return standardizeError(message, 'NOT_FOUND', field);
}
/**
* Helper to format authentication errors
*/
function formatAuthError(message) {
return standardizeError(message, 'AUTH_ERROR');
}
/**
* Helper to format forbidden/access errors
*/
function formatForbiddenError(message) {
return standardizeError(message, 'FORBIDDEN');
}
module.exports = {
errorFormatter,
standardizeError,
formatValidationError,
formatNotFoundError,
formatAuthError,
formatForbiddenError,
extractFieldFromError,
};