@cowwoc/requirements
Version:
A fluent API for enforcing design contracts with automatic message generation.
192 lines • 9.21 kB
JavaScript
import { NumberValidatorImpl, AbstractValidator, numberIsMultipleOf, numberIsNotMultipleOf, ValidationTarget, JavascriptValidatorsImpl, numberIsFinite, numberIsInfinite, numberIsNumber, numberIsNotNumber, collectionContainsSize, objectIsNotEmpty, objectIsEmpty, collectionSizeIsBetween, Type } from "../internal.mjs";
import { requireThatValueIsDefined } from "./Objects.mjs";
/**
* Validates the state of an object's size.
*/
class ObjectSizeValidatorImpl extends AbstractValidator {
objectValidator;
pluralizer;
/**
* @param scope - the application configuration
* @param configuration - the validator configuration
* @param objectValidator - the object's validator
* @param sizeName - the name of the object's size
* @param size - the object's size
* @param pluralizer - the type of elements in the object
* @param context - the contextual information set by a parent validator or the user
* @param failures - the list of validation failures
* @throws TypeError if `name` is `undefined` or `null`
* @throws RangeError if `name` contains whitespace, or is empty
* @throws AssertionError if `scope`, `configuration`, `value`, `context` or `failures` are null
*/
constructor(scope, configuration, objectValidator, sizeName, size, pluralizer, context, failures) {
super(scope, configuration, sizeName, size, context, failures);
requireThatValueIsDefined(objectValidator, "objectValidator");
requireThatValueIsDefined(pluralizer, "pluralizer");
this.objectValidator = objectValidator;
this.pluralizer = pluralizer;
}
isEqualTo(expected, name) {
const typeOfExpected = Type.of(expected);
if (typeOfExpected === Type.NUMBER) {
if (name !== undefined)
this.requireThatNameIsUnique(name);
if (this.value.validationFailed(v => v === expected)) {
this.addRangeError(collectionContainsSize(this.objectValidator, this.name, this.value.or(null), "must contain", this.name, expected, this.pluralizer).toString());
}
return this;
}
return super.isEqualTo(expected);
}
isNotEqualTo(unwanted, name) {
const typeOfExpected = Type.of(unwanted);
if (typeOfExpected === Type.NUMBER) {
if (name !== undefined)
this.requireThatNameIsUnique(name);
if (this.value.validationFailed(v => v !== unwanted)) {
this.addRangeError(collectionContainsSize(this.objectValidator, this.name, this.value.or(null), "may not contain", this.name, unwanted, this.pluralizer).toString());
}
return this;
}
return super.isEqualTo(unwanted);
}
isZero() {
if (this.value.validationFailed(value => value == 0)) {
this.failOnUndefinedOrNull();
this.addRangeError(objectIsEmpty(this.objectValidator).toString());
}
return this;
}
isNotZero() {
if (this.value.validationFailed(v => !(v == 0))) {
this.failOnUndefinedOrNull();
this.addRangeError(objectIsNotEmpty(this.objectValidator).toString());
}
return this;
}
isPositive() {
return this.isNotZero();
}
isNotPositive() {
return this.isZero();
}
isLessThan(maximumExclusive, name) {
if (name !== undefined)
this.requireThatNameIsUnique(name);
if (this.value.validationFailed(v => v < maximumExclusive)) {
this.failOnUndefinedOrNull();
this.addRangeError(collectionContainsSize(this.objectValidator, this.name, this.value.or(null), "must contain less than", name ?? null, maximumExclusive, this.pluralizer).toString());
}
return this;
}
isLessThanOrEqualTo(maximumInclusive, name) {
if (name !== undefined)
this.requireThatNameIsUnique(name);
if (this.value.validationFailed(v => v <= maximumInclusive)) {
this.failOnUndefinedOrNull();
this.addRangeError(collectionContainsSize(this.objectValidator, this.name, this.value.or(null), "may not contain more than", name ?? null, maximumInclusive, this.pluralizer).toString());
}
return this;
}
isGreaterThanOrEqualTo(minimumInclusive, name) {
if (name !== undefined)
this.requireThatNameIsUnique(name);
if (this.value.validationFailed(v => v >= minimumInclusive)) {
this.failOnUndefinedOrNull();
this.addRangeError(collectionContainsSize(this.objectValidator, this.name, this.value.or(null), "must contain at least", name ?? null, minimumInclusive, this.pluralizer).toString());
}
return this;
}
isGreaterThan(minimumExclusive, name) {
if (name !== undefined)
this.requireThatNameIsUnique(name);
if (this.value.validationFailed(v => v >= minimumExclusive)) {
this.failOnUndefinedOrNull();
this.addRangeError(collectionContainsSize(this.objectValidator, this.name, this.value.or(null), "must contain more than", name ?? null, minimumExclusive, this.pluralizer).toString());
}
return this;
}
isBetween(minimum, maximumExclusiveOrMinimumIsInclusive, maximum, maximumIsInclusive) {
const normalized = NumberValidatorImpl.normalizeIsBetweenParameters(minimum, maximumExclusiveOrMinimumIsInclusive, maximum, maximumIsInclusive);
const internalValidators = JavascriptValidatorsImpl.INTERNAL;
internalValidators.requireThatNumber(normalized.minimum, "minimum").
isLessThanOrEqualTo(normalized.maximum, "maximum");
if (this.value.validationFailed(v => ObjectSizeValidatorImpl.inBounds(v, normalized.minimum, normalized.minimumIsInclusive, normalized.maximum, normalized.maximumIsInclusive))) {
this.failOnUndefinedOrNull();
this.addRangeError(collectionSizeIsBetween(this, this.name, this.value.or(null), normalized.minimum, normalized.minimumIsInclusive, normalized.maximum, normalized.maximumIsInclusive, this.pluralizer).
toString());
}
return this;
}
/**
* @param value - the value being validated
* @param minimum - the lower bound of the range
* @param minimumIsInclusive - `true` if the lower bound of the range is inclusive
* @param maximum - the upper bound of the range
* @param maximumIsInclusive - `true` if the upper bound of the range is inclusive
* @returns `true` if the value is in bounds; false otherwise
*/
static inBounds(value, minimum, minimumIsInclusive, maximum, maximumIsInclusive) {
if (minimumIsInclusive) {
if (value < minimum)
return false;
}
else if (value <= minimum)
return false;
if (maximumIsInclusive)
return value <= maximum;
return value < maximum;
}
isMultipleOf(factor, name) {
if (name !== undefined)
this.requireThatNameIsUnique(name);
if (this.value.validationFailed(v => NumberValidatorImpl.valueIsMultipleOf(v, factor))) {
this.failOnUndefinedOrNull();
const messageBuilder = numberIsMultipleOf(this, name ?? null, factor);
this.objectValidator.value.ifValid(v => messageBuilder.withContext(v, this.objectValidator.getName()));
this.addRangeError(messageBuilder.toString());
}
return this;
}
isNotMultipleOf(factor, name) {
if (name !== undefined)
this.requireThatNameIsUnique(name);
if (this.value.validationFailed(v => !NumberValidatorImpl.valueIsMultipleOf(v, factor))) {
this.failOnUndefinedOrNull();
const messageBuilder = numberIsNotMultipleOf(this, name ?? null, factor);
this.objectValidator.value.ifValid(v => messageBuilder.withContext(v, this.objectValidator.getName()));
this.addRangeError(messageBuilder.toString());
}
return this;
}
isFinite() {
if (this.value.validationFailed(v => Number.isFinite(v))) {
this.failOnUndefinedOrNull();
this.addRangeError(numberIsFinite(this).toString());
}
return this;
}
isInfinite() {
if (this.value.validationFailed(v => !Number.isFinite(v) && !Number.isNaN(v))) {
this.failOnUndefinedOrNull();
this.addRangeError(numberIsInfinite(this).toString());
}
return this;
}
isNumber() {
if (this.value.validationFailed(v => !Number.isNaN(v))) {
this.failOnUndefinedOrNull();
this.addRangeError(numberIsNumber(this).toString());
}
return this;
}
isNotNumber() {
if (this.value.validationFailed(v => Number.isNaN(v))) {
this.failOnUndefinedOrNull();
this.addRangeError(numberIsNotNumber(this).toString());
}
return this;
}
}
export { ObjectSizeValidatorImpl };
//# sourceMappingURL=ObjectSizeValidatorImpl.mjs.map