one-of.js 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. const _ = require('lodash');
  2. const runner = require('./runner');
  3. module.exports = (validationChains, message) => (req, res, next) => {
  4. const run = chain => runner(req, getContext(chain));
  5. const contexts = _.flatMap(validationChains, chain => {
  6. return Array.isArray(chain) ? chain.map(getContext) : getContext(chain);
  7. });
  8. const promises = validationChains.map(chain => {
  9. const group = Array.isArray(chain) ? chain : [chain];
  10. return Promise.all(group.map(run)).then(results => _.flatten(results));
  11. });
  12. return Promise.all(promises).then(results => {
  13. req._validationContexts = (req._validationContexts || []).concat(contexts);
  14. req._validationErrors = req._validationErrors || [];
  15. const failedGroupContexts = findFailedGroupContexts(results, validationChains);
  16. req._validationOneOfFailures = (req._validationOneOfFailures || []).concat(failedGroupContexts);
  17. const empty = results.some(result => result.length === 0);
  18. if (!empty) {
  19. req._validationErrors.push({
  20. param: '_error',
  21. msg: getDynamicMessage(message || 'Invalid value(s)', req),
  22. nestedErrors: _.flatten(results, true)
  23. });
  24. }
  25. next();
  26. return results;
  27. }).catch(next);
  28. };
  29. function getContext(chain) {
  30. return chain._context;
  31. }
  32. function findFailedGroupContexts(results, validationChains) {
  33. return _(results)
  34. // If the group is free of errors, the empty array plays the trick of filtering such group.
  35. .flatMap((result, index) => result.length > 0 ? validationChains[index] : [])
  36. .map(getContext)
  37. .value();
  38. }
  39. function getDynamicMessage(message, req) {
  40. if (typeof message !== 'function') {
  41. return message;
  42. }
  43. return message({ req });
  44. }