const { Validator, addCustomMessages } = require('node-input-validator'); const { formatError } = require('../utils/formatError'); // {fieldName:message} eg:{email:"Invalid Email", password:"Password too short"} const formatValidationError = (error) => { const formatted = Object.entries(error) .map(([key, value]) => ({ field: key, message: value.message, })) .reduce((accumulator, currentValue) => { if (!accumulator[currentValue]) { accumulator[currentValue.field] = currentValue.message; } return accumulator; }, {}); return formatted; }; module.exports = { /** * Input Validator middleware for controller * @param {object} validationObject object defining body fields and its validation types eg:{email:required|email} * @param {object} _extendMessages object defining message to throw on validation error eg: {"email.required":"Email is required","email.email":"Invalid email"} * */ validateInput: (validationObject = {}, _extendMessages = {}) => async (req, res, next) => { const validation = new Validator(req.body, validationObject); addCustomMessages(_extendMessages); try { const isValid = await validation.check(); if (!isValid) { req.validationError = formatValidationError(validation.errors); } return next(); } catch (error) { req.validationError = error.message; return next(); } }, validateInputForGraphql: (fn = () => null, validationObject = {}, extendsMessages = {}) => async (parent, inputArgs, ...args) => { const validation = new Validator(JSON.parse(JSON.stringify(inputArgs)), validationObject); addCustomMessages(extendsMessages); try { const isValid = await validation.check(); if (!isValid) { return { success: false, code: 'ERROR_INPUT_VALIDATION', errors: Object.entries(validation.errors).map(([key, value]) => ({ path: key, message: value.message, })), }; } return fn(parent, inputArgs, ...args); } catch (error) { return formatError(error); } }, handleValidationErrorForViews: (req, res, viewModel, viewPath = '/', fieldsStoreKey, defaultValue = {}) => { const validationError = req.validationError; if (validationError) { // Remembers fields if validation error occurs Object.entries(defaultValue).forEach(([key, value]) => { viewModel[fieldsStoreKey][key] = value; }); if (typeof validationError === 'string') { viewModel.error = validationError; } else { viewModel.validationError = req.validationError; } return res.render(viewPath, viewModel); } }, handleValidationErrorForAPI: (req, res, next) => { const validationError = req.validationError; if (validationError) { let error; if (typeof validationError === 'string') { error = validationError; } else { error = req.validationError; } return res.json({ success: false, error }); } next(); }, };