matched-data.js 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. const _ = require('lodash');
  2. const selectFields = require('../utils/select-fields');
  3. module.exports = (req, options = {}) => {
  4. const fieldExtractor = createFieldExtractor(req, options);
  5. const validityFilter = createValidityFilter(req, options);
  6. const locationsFilter = createLocationFilter(options);
  7. return _(req._validationContexts)
  8. .flatMap(fieldExtractor)
  9. .filter(validityFilter)
  10. .map(field => field.instance)
  11. .filter(locationsFilter)
  12. .reduce((state, field) => _.set(state, field.path, field.value), {})
  13. .valueOf();
  14. };
  15. function createFieldExtractor(req, { includeOptionals }) {
  16. return context => [].concat(selectFields(req, context, {
  17. filterOptionals: includeOptionals !== true,
  18. // By the time we get here, all sanitizers did run, so we don't want double sanitization.
  19. sanitize: false
  20. })).map(instance => ({
  21. instance,
  22. context
  23. }));
  24. }
  25. function createValidityFilter(req, { onlyValidData }) {
  26. onlyValidData = onlyValidData === undefined ? true : onlyValidData;
  27. return !onlyValidData ? () => true : field => {
  28. const hasError = req._validationErrors.some(error => (
  29. error.param === field.instance.path &&
  30. error.location === field.instance.location
  31. ));
  32. const isFailedOneOfGroup = (req._validationOneOfFailures || []).includes(field.context);
  33. return !(hasError || isFailedOneOfGroup);
  34. };
  35. }
  36. function createLocationFilter({ locations }) {
  37. const allLocations = !Array.isArray(locations) || locations.length === 0;
  38. return allLocations ? () => true : field => locations.includes(field.location);
  39. }