79 lines
3 KiB
JavaScript
79 lines
3 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const _ = require("lodash");
|
|
function getDataMapKey(path, location) {
|
|
return `${location}:${path}`;
|
|
}
|
|
class Context {
|
|
constructor(fields, locations, stack, optional, message) {
|
|
this.fields = fields;
|
|
this.locations = locations;
|
|
this.stack = stack;
|
|
this.optional = optional;
|
|
this.message = message;
|
|
this._errors = [];
|
|
this.dataMap = new Map();
|
|
}
|
|
get errors() {
|
|
return this._errors;
|
|
}
|
|
getData(options = { requiredOnly: false }) {
|
|
// Have to store this.optional in a const otherwise TS thinks the value could have changed
|
|
// when the functions below run
|
|
const { optional } = this;
|
|
const checks = options.requiredOnly && optional
|
|
? [
|
|
(value) => value !== undefined,
|
|
(value) => (optional.nullable ? value != null : true),
|
|
(value) => (optional.checkFalsy ? value : true),
|
|
]
|
|
: [];
|
|
return _([...this.dataMap.values()])
|
|
.groupBy('originalPath')
|
|
.flatMap((instances, group) => {
|
|
const locations = _.uniqBy(instances, 'location');
|
|
// #331 - When multiple locations are involved, all of them must pass the validation.
|
|
// If none of the locations contain the field, we at least include one for error reporting.
|
|
// #458, #531 - Wildcards are an exception though: they may yield 0..* instances with different
|
|
// paths, so we may want to skip this filtering.
|
|
if (instances.length > 1 && locations.length > 1 && !group.includes('*')) {
|
|
const withValue = instances.filter(instance => instance.value !== undefined);
|
|
return withValue.length ? withValue : [instances[0]];
|
|
}
|
|
return instances;
|
|
})
|
|
.filter(instance => checks.every(check => check(instance.value)))
|
|
.valueOf();
|
|
}
|
|
addFieldInstances(instances) {
|
|
instances.forEach(instance => {
|
|
this.dataMap.set(getDataMapKey(instance.path, instance.location), Object.assign({}, instance));
|
|
});
|
|
}
|
|
setData(path, value, location) {
|
|
const instance = this.dataMap.get(getDataMapKey(path, location));
|
|
if (!instance) {
|
|
throw new Error('Attempt to write data that did not pre-exist in context');
|
|
}
|
|
instance.value = value;
|
|
}
|
|
addError(message, valueOrNestedErrors, meta) {
|
|
const msg = message || this.message || 'Invalid value';
|
|
if (meta) {
|
|
this._errors.push({
|
|
value: valueOrNestedErrors,
|
|
msg: typeof msg === 'function' ? msg(valueOrNestedErrors, meta) : msg,
|
|
param: meta.path,
|
|
location: meta.location,
|
|
});
|
|
}
|
|
else {
|
|
this._errors.push({
|
|
msg,
|
|
param: '_error',
|
|
nestedErrors: valueOrNestedErrors,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
exports.Context = Context;
|