/** * 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, };