@gp_jcisneros/errors
Version:
Error handling utilities for GreenPay microservices and validation middleware
309 lines (274 loc) • 8.87 kB
JavaScript
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,
};