UNPKG

@gp_jcisneros/errors

Version:

Error handling utilities for GreenPay microservices and validation middleware

309 lines (274 loc) 8.87 kB
const { ZodError: ZodValidationError } = require('zod'); const { ZodError } = require('./ZodError'); /** * Convierte errores de Zod a ZodError estandarizado * @param {ZodValidationError} zodError - Error de Zod * @param {string} integration - Nombre de la integración * @param {Object} customValidation - Validación personalizada * @returns {ZodError} - Error de validación estandarizado */ const convertZodErrorToValidationError = ( zodError, integration = 'default-integration', customValidation = null ) => { const error = ZodError.fromZodError(zodError, integration); if (customValidation) { error.additionalData = { ...error.additionalData, customValidation, }; } return error; }; /** * Crea un ZodError para campos requeridos * @param {string} field - Campo requerido * @param {string} integration - Nombre de la integración * @param {Object} customValidation - Validación personalizada * @returns {ZodError} - Error de validación */ const createRequiredFieldError = ( field, integration = 'default-integration', customValidation = null ) => { const error = ZodError.required(field, integration); if (customValidation) { error.additionalData = { validation: customValidation }; } return error; }; /** * Crea un ZodError para proveedores no soportados * @param {string} provider - Proveedor no soportado * @param {string} transactionType - Tipo de transacción * @param {string} integration - Nombre de la integración * @param {Object} customValidation - Validación personalizada * @returns {ZodError} - Error de validación */ const createUnsupportedProviderError = ( provider, transactionType, integration = 'default-integration', customValidation = null ) => { const error = ZodError.unsupportedProvider(provider, transactionType, integration); if (customValidation) { error.additionalData = { validation: customValidation }; } return error; }; /** * Crea un ZodError genérico para errores inesperados * @param {Error} error - Error original * @param {string} integration - Nombre de la integración * @returns {ZodError} - Error de validación */ const createGenericValidationError = ( error, integration = 'default-integration' ) => { return ZodError.generic(error, integration); }; /** * Middleware para validación dinámica basada en proveedor * @param {Function} createDynamicSchema - Función para crear schema dinámico * @param {string} transactionType - Tipo de transacción * @param {Object} customExtensions - Extensiones personalizadas * @param {string} integration - Nombre de la integración * @param {Function} getCustomValidation - Función para obtener validación personalizada * @param {Function} errorResponse - Función para responder con error * @returns {Function} - Middleware de validación */ const createDynamicSchemaValidation = ( createDynamicSchema, transactionType, customExtensions = {}, integration = 'default-integration', getCustomValidation = null, errorResponse = null ) => { return async (req, res, next) => { try { // Obtener el proveedor del campo bankProvider en paymentMethod const provider = req.body?.requestData?.paymentMethod?.bankProvider || req.body?.paymentMethod?.bankProvider || req.query?.bankProvider; if (!provider) { const customValidation = getCustomValidation ? await getCustomValidation('ZOD-002') : null; const error = createRequiredFieldError( 'bankProvider', integration, customValidation ); if (errorResponse) { return errorResponse(res, error); } return res.status(error.statusCode).json({ code: error.statusCode, status: 'failed', message: error.message, error: { code: error.errorCode, message: error.description, }, additionalData: error.additionalData, }); } // Crear el schema dinámico basado en baseSchema const schema = createDynamicSchema( provider, transactionType, customExtensions ); if (!schema) { const customValidation = getCustomValidation ? await getCustomValidation('ZOD-003') : null; const error = createUnsupportedProviderError( provider, transactionType, integration, customValidation ); if (errorResponse) { return errorResponse(res, error); } return res.status(error.statusCode).json({ code: error.statusCode, status: 'failed', message: error.message, error: { code: error.errorCode, message: error.description, }, additionalData: error.additionalData, }); } // Validar con el schema dinámico await schema.parseAsync({ body: req.body, params: req.params, query: req.query, }); next(); } catch (error) { if (error instanceof ZodValidationError) { const customValidation = getCustomValidation ? await getCustomValidation('ZOD-001') : null; const validationError = convertZodErrorToValidationError( error, integration, customValidation ); if (errorResponse) { return errorResponse(res, validationError); } return res.status(validationError.statusCode).json({ code: validationError.statusCode, status: 'failed', message: validationError.message, error: { code: validationError.errorCode, message: validationError.description, }, additionalData: validationError.additionalData, }); } const genericError = createGenericValidationError(error, integration); if (errorResponse) { return errorResponse(res, genericError); } return res.status(genericError.statusCode).json({ code: genericError.statusCode, status: 'failed', message: genericError.message, error: { code: genericError.errorCode, message: genericError.description, }, additionalData: genericError.additionalData, }); } }; }; /** * Middleware para validación usando schema base * @param {Object} baseSchema - Schema base de Zod * @param {Object} customExtensions - Extensiones personalizadas * @param {string} integration - Nombre de la integración * @param {Function} getCustomValidation - Función para obtener validación personalizada * @param {Function} errorResponse - Función para responder con error * @returns {Function} - Middleware de validación */ const createBaseSchemaValidation = ( baseSchema, customExtensions = {}, integration = 'default-integration', getCustomValidation = null, errorResponse = null ) => { return async (req, res, next) => { try { const schema = baseSchema.extend(customExtensions); // Validar con el baseSchema await schema.parseAsync({ body: req.body, params: req.params, query: req.query, }); next(); } catch (error) { if (error instanceof ZodValidationError) { const customValidation = getCustomValidation ? await getCustomValidation('ZOD-001') : null; const validationError = convertZodErrorToValidationError( error, integration, customValidation ); if (errorResponse) { return errorResponse(res, validationError); } return res.status(validationError.statusCode).json({ code: validationError.statusCode, status: 'failed', message: validationError.message, error: { code: validationError.errorCode, message: validationError.description, }, additionalData: validationError.additionalData, }); } const genericError = createGenericValidationError(error, integration); if (errorResponse) { return errorResponse(res, genericError); } return res.status(genericError.statusCode).json({ code: genericError.statusCode, status: 'failed', message: genericError.message, error: { code: genericError.errorCode, message: genericError.description, }, additionalData: genericError.additionalData, }); } }; }; module.exports = { convertZodErrorToValidationError, createRequiredFieldError, createUnsupportedProviderError, createGenericValidationError, createDynamicSchemaValidation, createBaseSchemaValidation, };