UNPKG

3.14 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.Context = void 0;
4const _ = require("lodash");
5function getDataMapKey(path, location) {
6 return `${location}:${path}`;
7}
8class Context {
9 constructor(fields, locations, stack, optional, message) {
10 this.fields = fields;
11 this.locations = locations;
12 this.stack = stack;
13 this.optional = optional;
14 this.message = message;
15 this._errors = [];
16 this.dataMap = new Map();
17 }
18 get errors() {
19 return this._errors;
20 }
21 getData(options = { requiredOnly: false }) {
22 // Have to store this.optional in a const otherwise TS thinks the value could have changed
23 // when the functions below run
24 const { optional } = this;
25 const checks = options.requiredOnly && optional
26 ? [
27 (value) => value !== undefined,
28 (value) => (optional.nullable ? value != null : true),
29 (value) => (optional.checkFalsy ? value : true),
30 ]
31 : [];
32 return _([...this.dataMap.values()])
33 .groupBy('originalPath')
34 .flatMap((instances, group) => {
35 const locations = _.uniqBy(instances, 'location');
36 // #331 - When multiple locations are involved, all of them must pass the validation.
37 // If none of the locations contain the field, we at least include one for error reporting.
38 // #458, #531 - Wildcards are an exception though: they may yield 0..* instances with different
39 // paths, so we may want to skip this filtering.
40 if (instances.length > 1 && locations.length > 1 && !group.includes('*')) {
41 const withValue = instances.filter(instance => instance.value !== undefined);
42 return withValue.length ? withValue : [instances[0]];
43 }
44 return instances;
45 })
46 .filter(instance => checks.every(check => check(instance.value)))
47 .valueOf();
48 }
49 addFieldInstances(instances) {
50 instances.forEach(instance => {
51 this.dataMap.set(getDataMapKey(instance.path, instance.location), Object.assign({}, instance));
52 });
53 }
54 setData(path, value, location) {
55 const instance = this.dataMap.get(getDataMapKey(path, location));
56 if (!instance) {
57 throw new Error('Attempt to write data that did not pre-exist in context');
58 }
59 instance.value = value;
60 }
61 addError(message, valueOrNestedErrors, meta) {
62 const msg = message || this.message || 'Invalid value';
63 if (meta) {
64 this._errors.push({
65 value: valueOrNestedErrors,
66 msg: typeof msg === 'function' ? msg(valueOrNestedErrors, meta) : msg,
67 param: meta.path,
68 location: meta.location,
69 });
70 }
71 else {
72 this._errors.push({
73 msg,
74 param: '_error',
75 nestedErrors: valueOrNestedErrors,
76 });
77 }
78 }
79}
80exports.Context = Context;