You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

59 lines
1.8 KiB
JavaScript

"use strict";
const defaultValue = require("default-value");
const ValidationError = require("@validatem/error");
const combinator = require("@validatem/combinator");
const annotateErrors = require("@validatem/annotate-errors");
const virtualProperty = require("@validatem/virtual-property");
const validationResult = require("@validatem/validation-result");
module.exports = function (rules) {
if (rules.key == null && rules.value == null) {
throw new Error(`Must specify either a 'key' or 'value' property in the ruleset`);
} else {
let keyRules = defaultValue(rules.key, []);
let valueRules = defaultValue(rules.value, []);
let validator = combinator((object, applyValidators) => {
let newObject = {};
let allErrors = [];
if (typeof object !== "object" || Array.isArray(object)) {
throw new ValidationError("Must be an object");
} else {
// NOTE: Reflect.ownEntries is used here to ensure we capture the Symbol-typed keys as well
for (let key of Reflect.ownKeys(object)) {
let value = object[key];
let keyAsString = key.toString(); // Again, to deal with Symbol-typed keys.
let { errors: keyErrors, newValue: newKey } = applyValidators(key, keyRules);
let { errors: valueErrors, newValue } = applyValidators(value, valueRules);
let annotatedKeyErrors = annotateErrors({
pathSegments: [ keyAsString, virtualProperty("key") ],
errors: keyErrors
});
let annotatedValueErrors = annotateErrors({
pathSegments: [ keyAsString, virtualProperty("value") ],
errors: valueErrors
});
newObject[newKey] = newValue;
allErrors.push(...annotatedKeyErrors, ...annotatedValueErrors);
}
return validationResult({
errors: allErrors,
newValue: newObject
});
}
});
validator.callIfNull = false;
return validator;
}
};