New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

optimal

Package Overview
Dependencies
Maintainers
1
Versions
68
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

optimal - npm Package Compare versions

Comparing version 4.3.0 to 5.0.0-alpha.1

dts/createPredicate.d.ts

2301

esm/index.js

@@ -1,1393 +0,1631 @@

function isObject(value) {
return !!value && typeof value === 'object' && !Array.isArray(value);
}
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
// Bundled with Packemon: https://packemon.dev
// Platform: browser, Support: stable, Format: esm
class ValidationError extends Error {
constructor(message, path = '', value = undefined) {
super(message);
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
_defineProperty(this, "errors", []);
_defineProperty(this, "path", void 0);
_defineProperty(this, "value", void 0);
this.name = 'ValidationError';
this.path = path;
this.value = value;
if (path) {
const key = pathKey(path);
this.message = `${key.includes('[') ? `Invalid member "${key}".` : `Invalid field "${key}".`} ${this.message}`;
}
}
return target;
};
addError(error) {
const validError = error instanceof ValidationError ? error : new ValidationError(error.message);
const hasSameError = this.errors.some(e => e.message === error.message);
return _extends.apply(this, arguments);
if (hasSameError) {
return;
}
this.errors.push(validError);
this.message += '\n';
this.message += error.message.split('\n').map(line => line.match(/^\s+-/) ? ` ${line}` : ` - ${line}`).join('\n');
}
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
function isObject(value) {
return !!value && typeof value === 'object' && !Array.isArray(value);
}
_setPrototypeOf(subClass, superClass);
function isSchema(value) {
return isObject(value) && typeof value.schema === 'function' && typeof value.type === 'function' && typeof value.validate === 'function';
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
function isValidDate(value) {
return Object.prototype.toString.call(value) === '[object Date]' && !Number.isNaN(value.getTime()) && value.toString() !== 'Invalid Date';
}
return _setPrototypeOf(o, p);
function isValidNumber(value) {
return typeof value === 'number' && !Number.isNaN(value);
}
function logUnknown(unknownFields, pathPrefix) {
var unknownKeys = Object.keys(unknownFields);
function isValidString(value) {
return typeof value === 'string' && value !== '';
}
if (unknownKeys.length > 0) {
var message = pathPrefix ? "Unknown \"" + pathPrefix + "\" fields" : 'Unknown fields';
throw new Error(message + ": " + unknownKeys.join(', ') + ".");
function createArray(value) {
if (value === undefined) {
return [];
}
return Array.isArray(value) ? [...value] : [value];
}
function typeOf(value) {
if (Array.isArray(value)) {
return 'array';
function createDate(value) {
if (value instanceof Date) {
return value;
}
if (isObject(value)) {
return value.constructor.name === 'Object' ? 'object' : 'instance';
if (value === undefined || value === null) {
return new Date();
}
switch (typeof value) {
case 'boolean':
case 'function':
case 'number':
case 'string':
return typeof value;
return new Date(value);
}
default:
return 'unknown';
}
function createObject(value) {
return isObject(value) ? { ...value
} : {};
}
/**
* Native `instanceof` checks are problematic, as cross realm checks fail.
* They will also fail when comparing against source and compiled files.
* So emulate an `instanceof` check by comparing constructor names.
*/
var Predicate = function () {
function Predicate(type, defaultValue, bypassFactory) {
if (bypassFactory === void 0) {
bypassFactory = false;
}
this.defaultValue = void 0;
this.schema = void 0;
this.type = void 0;
this.checks = [];
this.defaultValueFactory = void 0;
this.deprecatedMessage = '';
this.errorMessage = '';
this.isNever = false;
this.isNullable = false;
this.isRequired = false;
this.noErrorPrefix = false;
function instanceOf(object, contract) {
if (!object || typeof object !== 'object') {
return false;
}
if (typeof defaultValue === 'function' && !bypassFactory) {
this.defaultValueFactory = defaultValue;
} else {
this.defaultValue = defaultValue;
if (object instanceof contract) {
return true;
}
let current = object;
while (current) {
if (current.constructor.name === 'Object') {
return false;
}
this.type = type;
if (current.constructor.name === contract.name || current instanceof Error && current.name === contract.name) {
return true;
} // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
current = Object.getPrototypeOf(current);
}
var _proto = Predicate.prototype;
return false;
}
_proto.and = function and() {
var _this = this;
function invalid(condition, message, path = '', value = undefined) {
if (condition) {
return;
}
for (var _len = arguments.length, keys = new Array(_len), _key = 0; _key < _len; _key++) {
keys[_key] = arguments[_key];
}
throw new ValidationError(message, path, value);
}
if ("production" !== process.env.NODE_ENV) {
this.invariant(keys.length > 0, 'AND requires a list of field names.');
this.addCheck(function (path) {
var _this$schema$parentSt, _this$schema;
function invariant(condition, message) {
if (condition) {
return;
}
var andKeys = [_this.key(path)].concat(keys);
var struct = (_this$schema$parentSt = (_this$schema = _this.schema) == null ? void 0 : _this$schema.parentStruct) != null ? _this$schema$parentSt : {};
var undefs = andKeys.filter(function (key) {
return struct[key] === undefined || struct[key] === null;
});
throw new Error(message);
}
if (undefs.length === andKeys.length) {
return;
}
function logUnknown(unknownFields, pathPrefix) {
const unknownKeys = Object.keys(unknownFields);
_this.invariant(undefs.length === 0, "All of these fields must be defined: " + andKeys.join(', '));
});
}
if (unknownKeys.length > 0) {
throw new Error(`${pathPrefix ? `Unknown "${pathPrefix}" fields` : 'Unknown fields'}: ${unknownKeys.join(', ')}.`);
}
}
return this;
};
function pathKey(path) {
if (path.endsWith(']')) {
const index = path.lastIndexOf('[');
return index > 0 ? path.slice(index) : path;
}
_proto.cast = function cast(value) {
return value;
};
const index = path.lastIndexOf('.');
return index > 0 ? path.slice(index + 1) : path;
}
_proto.custom = function custom(callback) {
var _this2 = this;
function tryAndCollect(validator, validError, collectErrors) {
let result = false;
if ("production" !== process.env.NODE_ENV) {
this.invariant(typeof callback === 'function', 'Custom blueprints require a validation function.');
this.addCheck(function (path, value) {
try {
callback(value, _this2.schema);
} catch (error) {
_this2.invariant(false, error.message, path);
}
});
try {
const value = validator();
if (typeof value === 'boolean') {
result = value;
}
} catch (error) {
if (error instanceof Error && collectErrors) {
validError.addError(error);
} else {
throw error;
}
}
return this;
};
return result;
}
_proto.default = function _default() {
var _this$schema$struct, _this$schema2;
class OptimalError extends ValidationError {
constructor() {
super('');
var value = this.defaultValueFactory ? this.defaultValueFactory((_this$schema$struct = (_this$schema2 = this.schema) == null ? void 0 : _this$schema2.struct) != null ? _this$schema$struct : {}) : this.defaultValue;
_defineProperty(this, "file", '');
if (value === null) {
return null;
}
_defineProperty(this, "schema", '');
return this.cast(value);
};
this.name = 'OptimalError';
}
_proto.deprecate = function deprecate(message) {
if ("production" !== process.env.NODE_ENV) {
this.invariant(typeof message === 'string' && !!message, 'A non-empty string is required for deprecated messages.');
}
addError(error) {
const validError = error instanceof ValidationError ? error : new ValidationError(error.message);
this.errors.push(validError); // Avoid indenting at this level
this.deprecatedMessage = message;
return this;
};
this.message = `${this.message}\n${error.message}`.trim();
}
_proto.invariant = function invariant(condition, message, path) {
if (path === void 0) {
path = '';
}
/**
* Run all validation checks that have been enqueued and return a type casted value.
* If a value is undefined, inherit the default value, else throw if required.
* If nullable and the value is null, return early.
*/
function validate(state, validators, initialValue, path = '', {
collectErrors = true,
currentObject = {},
rootObject = currentObject
} = {}) {
const {
defaultValue,
metadata
} = state;
let value = initialValue; // Handle undefined
if (value === undefined) {
value = typeof defaultValue === 'function' ? defaultValue(path, currentObject, rootObject) : defaultValue;
invalid(!state.required, 'Field is required and must be defined.', path);
} else {
if (process.env.NODE_ENV !== "production" && metadata.deprecatedMessage) {
// eslint-disable-next-line no-console
console.info(`Field "${path}" is deprecated. ${metadata.deprecatedMessage}`);
}
if ("production" !== process.env.NODE_ENV) {
if (condition) {
return;
}
invalid(!state.never, 'Field should never be used.', path);
} // Handle null
var _ref = this.schema || {},
filePath = _ref.filePath,
schemaName = _ref.schemaName;
var error = this.errorMessage || message;
var prefix = '';
if (value === null) {
invalid(state.nullable, 'Null is not allowed.', path);
} // Run validations and produce a new value
if (path) {
prefix += schemaName ? "Invalid " + schemaName + " field \"" + path + "\"" : "Invalid field \"" + path + "\"";
} else if (schemaName) {
prefix += schemaName;
}
if (filePath) {
prefix += " in " + filePath;
const optimalError = new OptimalError();
validators.forEach(test => {
if (test.skipIfNull && value === null || test.skipIfOptional && !state.required && value === state.defaultValue) {
return;
}
tryAndCollect(() => {
const result = test.validate(value, path, {
collectErrors,
currentObject,
rootObject
});
if (result !== undefined) {
value = result;
}
}, optimalError, collectErrors);
});
var nextError = prefix && !this.noErrorPrefix ? new Error(prefix + ". " + error) : new Error(error);
throw nextError;
}
if (optimalError.errors.length > 0) {
throw optimalError;
}
return value;
}
function createSchema({
api,
cast,
defaultValue,
type
}, criteria = []) {
const state = {
defaultValue,
metadata: {},
never: false,
nullable: false,
required: false,
type
};
const validators = [];
criteria.forEach(crit => {
if (typeof crit === 'function') {
const validator = crit(state);
_proto.message = function message(_message) {
if ("production" !== process.env.NODE_ENV) {
this.invariant(typeof _message === 'string' && !!_message, 'A non-empty string is required for custom messages.');
if (validator) {
validators.push(validator);
}
} else {
validators.push(crit);
}
});
const schema = {
schema() {
return type;
},
this.errorMessage = _message;
return this;
};
type() {
return state.type;
},
_proto.never = function never() {
this.defaultValue = undefined;
this.isNever = true;
return this;
};
validate(value, path, options) {
const result = validate(state, validators, value, path, options);
return cast && result !== null ? cast(result) : result;
}
_proto.notNullable = function notNullable() {
this.isNullable = false;
return this;
};
Object.entries(api).forEach(([name, method]) => {
Object.defineProperty(schema, name, {
enumerable: true,
// Create a new schema so that our chainable API is immutable
value: (...args) => createSchema({
api,
cast,
defaultValue,
type
}, [...criteria, nextState => method(nextState, ...args)])
});
});
return schema;
}
/**
* Require field array to not be empty.
*/
_proto.nullable = function nullable() {
this.isNullable = true;
return this;
};
_proto.only = function only() {
var _this3 = this;
function notEmpty$2(state, options = {}) {
return {
skipIfNull: true,
if ("production" !== process.env.NODE_ENV) {
var defaultValue = this.default();
this.invariant(typeof defaultValue === this.type, "Only requires a default " + this.type + " value.");
this.addCheck(function (path, value) {
_this3.invariant(value === defaultValue, "Value may only be \"" + String(defaultValue) + "\".", path);
});
validate(value, path) {
invalid(value.length > 0, options.message ?? 'Array cannot be empty.', path, value);
}
return this;
};
}
/**
* Require field array items to be of a specific schema type.
* Will rebuild the array and type cast values.
*/
_proto.or = function or() {
var _this4 = this;
for (var _len2 = arguments.length, keys = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
keys[_key2] = arguments[_key2];
}
function of$5(state, itemsSchema) {
if (process.env.NODE_ENV !== "production") {
invariant(isSchema(itemsSchema), 'A schema is required for array items.');
}
if ("production" !== process.env.NODE_ENV) {
this.invariant(keys.length > 0, 'OR requires a list of field names.');
this.addCheck(function (path) {
var _this4$schema$parentS, _this4$schema;
state.type += `<${itemsSchema.type()}>`;
return {
skipIfNull: true,
var orKeys = [_this4.key(path)].concat(keys);
var struct = (_this4$schema$parentS = (_this4$schema = _this4.schema) == null ? void 0 : _this4$schema.parentStruct) != null ? _this4$schema$parentS : {};
var defs = orKeys.filter(function (key) {
return typeof struct[key] !== 'undefined' && struct[key] !== null;
});
validate(value, path, validateOptions) {
if (!Array.isArray(value)) {
return [];
}
_this4.invariant(defs.length > 0, "At least one of these fields must be defined: " + orKeys.join(', '));
const nextValue = [...value];
value.forEach((item, i) => {
nextValue[i] = itemsSchema.validate(item, `${path}[${i}]`, validateOptions);
});
return nextValue;
}
return this;
};
}
/**
* Require field array to be of a specific size.
*/
_proto.required = function required(state) {
if (state === void 0) {
state = true;
}
this.isRequired = state;
return this;
};
function sizeOf$2(state, size, options = {}) {
if (process.env.NODE_ENV !== "production") {
invariant(typeof size === 'number' && size > 0, 'Size of requires a non-zero positive number.');
}
_proto.run = function run(initialValue, path, schema) {
this.schema = schema;
this.defaultValue = this.default();
var value = initialValue;
return {
skipIfNull: true,
if (value === undefined) {
if (!this.isRequired) {
value = this.defaultValue;
} else if ("production" !== process.env.NODE_ENV) {
this.invariant(false, 'Field is required and must be defined.', path);
}
} else if ("production" !== process.env.NODE_ENV) {
if (this.deprecatedMessage) {
console.info("Field \"" + path + "\" is deprecated. " + this.deprecatedMessage);
}
if (this.isNever) {
this.invariant(false, 'Field should never be used.', path);
}
validate(value, path) {
invalid(value.length === size, options.message ?? `Array length must be ${size}.`, path, value);
}
if (value === null) {
if (this.isNullable) {
return null;
}
};
}
if ("production" !== process.env.NODE_ENV) {
this.invariant(false, 'Null is not allowed.', path);
}
} else {
this.checkType(path, value);
const arrayCriteria = /*#__PURE__*/Object.freeze({
__proto__: null,
notEmpty: notEmpty$2,
of: of$5,
sizeOf: sizeOf$2
});
/**
* Require this field to only be false.
*/
function onlyFalse(state, options = {}) {
state.defaultValue = false;
return {
validate(value, path) {
invalid(!value, options.message ?? 'May only be `false`.', path, value);
}
var finalValue = value;
this.schema.currentPath = path;
this.schema.currentValue = finalValue;
finalValue = this.doRun(finalValue, path);
finalValue = this.validate(finalValue, path);
return this.cast(finalValue);
};
}
/**
* Require this field to only be true.
*/
_proto.typeAlias = function typeAlias() {
return this.type;
};
_proto.validate = function validate(value, path) {
var _this5 = this;
if (path === void 0) {
path = '';
function onlyTrue(state, options = {}) {
state.defaultValue = true;
return {
validate(value, path) {
invalid(value, options.message ?? 'May only be `true`.', path, value);
}
var nextValue = value;
this.checkType(path, value);
this.checks.forEach(function (checker) {
var result = checker.call(_this5, path, nextValue);
if (typeof result !== 'undefined') {
nextValue = result;
}
});
return nextValue;
};
}
_proto.xor = function xor() {
var _this6 = this;
const booleanCriteria = /*#__PURE__*/Object.freeze({
__proto__: null,
onlyFalse: onlyFalse,
onlyTrue: onlyTrue
});
/**
* Require this field to be an instance of the defined class.
*/
for (var _len3 = arguments.length, keys = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
keys[_key3] = arguments[_key3];
}
function of$4(state, ref, loose = false) {
if (process.env.NODE_ENV !== "production") {
invariant(typeof ref === 'function', 'A class reference is required.');
}
if ("production" !== process.env.NODE_ENV) {
this.invariant(keys.length > 0, 'XOR requires a list of field names.');
this.addCheck(function (path) {
var _this6$schema$parentS, _this6$schema;
state.type = ref.name ?? ref.constructor.name;
return {
skipIfNull: true,
var xorKeys = [_this6.key(path)].concat(keys);
var struct = (_this6$schema$parentS = (_this6$schema = _this6.schema) == null ? void 0 : _this6$schema.parentStruct) != null ? _this6$schema$parentS : {};
var defs = xorKeys.filter(function (key) {
return typeof struct[key] !== 'undefined' && struct[key] !== null;
});
_this6.invariant(defs.length === 1, "Only one of these fields may be defined: " + xorKeys.join(', '));
});
validate(value, path) {
invalid(typeof ref === 'function' && (value instanceof ref || loose && isObject(value) && instanceOf(value, ref)), `Must be an instance of "${state.type}".`, path, value);
}
return this;
};
}
_proto.addCheck = function addCheck(checker) {
this.checks.push(checker);
return this;
};
const classCriteria = /*#__PURE__*/Object.freeze({
__proto__: null,
of: of$4
});
/**
* Map a list of field names that must be defined alongside this field.
*/
_proto.checkType = function checkType(path, value) {
if ("production" !== process.env.NODE_ENV) {
var displayValue = this.extractDisplayValue(value);
function and(state, ...keys) {
if (process.env.NODE_ENV !== "production") {
invariant(keys.length > 0, 'AND requires a list of field names.');
}
switch (this.type) {
case 'array':
case 'tuple':
this.invariant(Array.isArray(value), "Must be an array, received " + displayValue + ".", path);
break;
return {
validate(value, path, {
currentObject
}) {
const andKeys = [...new Set([pathKey(path), ...keys])].sort();
const undefs = andKeys.filter(key => currentObject?.[key] === undefined || currentObject?.[key] === null); // Only error once when one of the struct is defined
case 'custom':
case 'instance':
case 'union':
break;
if (undefs.length === andKeys.length) {
return;
}
case 'object':
case 'shape':
this.invariant(isObject(value), "Must be a plain object, received " + displayValue + ".", path);
break;
invalid(undefs.length === 0, `All of these fields must be defined: ${andKeys.join(', ')}`);
}
default:
this.invariant(typeof value === this.type, "Must be a " + this.type + ", received " + displayValue + ".", path);
break;
}
}
};
}
/**
* Set a callback to run custom validation logic.
*/
_proto.extractDisplayValue = function extractDisplayValue(value) {
var type = typeOf(value);
var displayValue = '';
if (type === 'string') {
displayValue = "\"" + value + "\"";
} else if (type === 'number' || type === 'boolean' || value === null || value === undefined) {
displayValue = String(value);
} else {
displayValue = type;
function custom$1(state, validator) {
if (process.env.NODE_ENV !== "production") {
invariant(typeof validator === 'function', 'Custom requires a validation function.');
}
return {
validate(value, path, validateOptions) {
try {
validator(value, path, validateOptions);
} catch (error) {
if (error instanceof Error) {
invalid(false, error.message, path, value);
}
}
}
return displayValue;
};
}
/**
* Set a message to log when this field is present.
*/
_proto.isOptionalDefault = function isOptionalDefault(value) {
return !this.isRequired && value === this.default();
};
_proto.key = function key(path) {
var index = path.lastIndexOf('.');
return index > 0 ? path.slice(index + 1) : path;
};
function deprecate(state, message) {
if (process.env.NODE_ENV !== "production") {
invariant(isValidString(message), 'A non-empty string is required for deprecated messages.');
}
_proto.doRun = function doRun(value, path) {
return value;
};
state.metadata.deprecatedMessage = message;
}
/**
* Mark that this field should never be used.
*/
return Predicate;
}();
function custom(callback, defaultValue) {
return new Predicate('custom', defaultValue).custom(callback);
function never(state) {
state.defaultValue = undefined;
state.never = true;
}
function func(defaultValue) {
if (defaultValue === void 0) {
defaultValue = null;
}
/**
* Disallow null values.
*/
return new Predicate('function', defaultValue, true).nullable();
function notNullable(state) {
state.nullable = false;
}
/**
* Require this field to NOT be explicitly defined.
*/
var Schema = function () {
function Schema(blueprint) {
this.blueprint = void 0;
this.currentPath = '';
this.currentValue = null;
this.filePath = '';
this.initialStruct = {};
this.parentPath = '';
this.parentStruct = {};
this.struct = {};
this.schemaName = '';
this.unknown = false;
if ("production" !== process.env.NODE_ENV) {
if (!isObject(blueprint)) {
throw new TypeError('A schema blueprint is required.');
}
}
function notRequired(state) {
state.required = false;
}
/**
* Allow null values.
*/
this.blueprint = blueprint;
}
var _proto = Schema.prototype;
function nullable(state) {
state.nullable = true;
}
/**
* Mark that this field can ONLY use a value that matches the default value.
*/
_proto.allowUnknown = function allowUnknown() {
this.unknown = true;
return this;
};
_proto.build = function build(struct, pathPrefix) {
var _this = this;
function only(state) {
const {
defaultValue
} = state;
if (pathPrefix === void 0) {
pathPrefix = '';
}
if (process.env.NODE_ENV !== "production") {
invariant(defaultValue !== null && defaultValue !== undefined, 'Only requires a non-empty default value.');
}
if ("production" !== process.env.NODE_ENV) {
if (!isObject(struct)) {
throw new TypeError("Schema requires a plain object, found " + typeOf(struct) + ".");
}
return {
validate(value, path) {
invalid(value === defaultValue, `Value may only be "${defaultValue}".`, path, value);
}
this.initialStruct = _extends({}, struct);
this.struct = _extends({}, struct);
};
}
/**
* Map a list of field names that must have at least 1 defined.
*/
var unknownFields = _extends({}, struct);
Object.keys(this.blueprint).forEach(function (baseKey) {
var key = baseKey;
var value = struct[key];
var predicate = _this.blueprint[key];
var path = String(pathPrefix ? pathPrefix + "." + key : key);
function or(state, ...keys) {
if (process.env.NODE_ENV !== "production") {
invariant(keys.length > 0, 'OR requires a list of field names.');
}
if (predicate instanceof Predicate || isObject(predicate) && predicate.constructor.name.endsWith('Predicate')) {
_this.parentPath = baseKey;
_this.parentStruct = _this.initialStruct;
_this.struct[key] = predicate.run(value, path, _this);
} else if ("production" !== process.env.NODE_ENV) {
throw new Error("Unknown blueprint for \"" + path + "\". Must be a predicate.");
}
delete unknownFields[key];
});
if (this.unknown) {
Object.assign(this.struct, unknownFields);
} else if ("production" !== process.env.NODE_ENV) {
logUnknown(unknownFields, pathPrefix);
return {
validate(value, path, {
currentObject
}) {
const orKeys = [...new Set([pathKey(path), ...keys])].sort();
const defs = orKeys.filter(key => currentObject?.[key] !== undefined && currentObject?.[key] !== null);
invalid(defs.length > 0, `At least one of these fields must be defined: ${orKeys.join(', ')}`);
}
return this.struct;
};
}
/**
* Require this field to be explicitly defined.
*/
_proto.setFile = function setFile(name) {
this.filePath = name;
return this;
};
_proto.setName = function setName(name) {
this.schemaName = name;
return this;
};
function required(state) {
state.required = true;
}
/**
* TODO
*/
return Schema;
}();
function optimal(struct, blueprint, options) {
if (options === void 0) {
options = {};
function when(state, condition, pass, fail) {
if (process.env.NODE_ENV !== "production") {
invariant(isSchema(pass), 'A schema is required when the condition passes.');
}
if ("production" !== process.env.NODE_ENV) {
if (!isObject(options)) {
throw new TypeError('Optimal options must be a plain object.');
if (fail !== undefined) {
if (process.env.NODE_ENV !== "production") {
invariant(isSchema(fail), 'A schema is required when the condition fails.');
}
}
var schema = new Schema(blueprint);
return {
validate(value, path, validateOptions) {
const passed = typeof condition === 'function' ? condition(value, validateOptions.currentObject, validateOptions.rootObject) : condition === value;
if (options.name) {
schema.setName(options.name);
}
if (passed) {
return pass.validate(value, path);
}
if (options.file) {
schema.setFile(options.file);
}
if (fail) {
return fail.validate(value, path, validateOptions);
}
if (options.unknown) {
schema.allowUnknown();
}
return undefined;
}
return schema.build(struct, options.prefix);
};
}
/**
* Map a list of field names that must not be defined alongside this field.
*/
var CollectionPredicate = function (_Predicate) {
_inheritsLoose(CollectionPredicate, _Predicate);
function CollectionPredicate() {
return _Predicate.apply(this, arguments) || this;
function xor(state, ...keys) {
if (process.env.NODE_ENV !== "production") {
invariant(keys.length > 0, 'XOR requires a list of field names.');
}
var _proto = CollectionPredicate.prototype;
_proto.sizeOf = function sizeOf(length) {
var _this = this;
if ("production" !== process.env.NODE_ENV) {
this.invariant(typeof length === 'number' && length > 0, 'Size requires a non-zero positive number.');
this.addCheck(function (path, value) {
if (_this.isNullable && value === null) {
return;
}
if (Array.isArray(value)) {
_this.invariant(value.length === length, "Array length must be " + length + ".", path);
} else if (typeof value === 'string') {
_this.invariant(value.length === length, "String length must be " + length + ".", path);
} else if (typeof value === 'object' && value) {
_this.invariant(Object.keys(value).length === length, "Object must have " + length + " properties.", path);
} else {
_this.invariant(false, 'Unknown type for size of checks.', path);
}
});
return {
validate(value, path, {
currentObject
}) {
const xorKeys = [...new Set([pathKey(path), ...keys])].sort();
const defs = xorKeys.filter(key => currentObject?.[key] !== undefined && currentObject?.[key] !== null);
invalid(defs.length === 1, `Only one of these fields may be defined: ${xorKeys.join(', ')}`);
}
return this;
};
}
return CollectionPredicate;
}(Predicate);
const commonCriteria = /*#__PURE__*/Object.freeze({
__proto__: null,
and: and,
custom: custom$1,
deprecate: deprecate,
never: never,
notNullable: notNullable,
notRequired: notRequired,
nullable: nullable,
only: only,
or: or,
required: required,
when: when,
xor: xor
});
/**
* Require field value to be after the provided date.
*/
var ArrayPredicate = function (_CollectionPredicate) {
_inheritsLoose(ArrayPredicate, _CollectionPredicate);
function after(state, date, options = {}) {
const afterDate = createDate(date);
function ArrayPredicate(contents, defaultValue) {
var _this;
if (process.env.NODE_ENV !== "production") {
invariant(isValidDate(afterDate), 'After date must be a valid date.');
}
if (contents === void 0) {
contents = null;
}
return {
skipIfNull: true,
if (defaultValue === void 0) {
defaultValue = [];
validate(value, path) {
invalid(isValidDate(value) && value > afterDate, options.message ?? `Date must come after ${afterDate.toLocaleDateString()}.`, path, value);
}
_this = _CollectionPredicate.call(this, 'array', defaultValue) || this;
_this.contents = null;
_this.contents = contents;
};
}
/**
* Require field value to be before the provided date.
*/
if (contents instanceof Predicate) {
_this.addCheck(function (path, value) {
var nextValue = [].concat(value);
value.forEach(function (item, i) {
nextValue[i] = contents.run(item, path + "[" + i + "]", _this.schema);
});
return nextValue;
});
} else if ("production" !== process.env.NODE_ENV && contents) {
_this.invariant(false, 'A blueprint is required for array contents.');
}
return _this;
function before(state, date, options = {}) {
const beforeDate = createDate(date);
if (process.env.NODE_ENV !== "production") {
invariant(isValidDate(beforeDate), 'Before date must be a valid date.');
}
var _proto = ArrayPredicate.prototype;
return {
skipIfNull: true,
_proto.cast = function cast(value) {
if (value === undefined) {
return [];
validate(value, path) {
invalid(isValidDate(value) && value < beforeDate, options.message ?? `Date must come before ${beforeDate.toLocaleDateString()}.`, path, value);
}
return Array.isArray(value) ? value : [value];
};
}
/**
* Require field value to be between 2 date ranges.
*/
_proto.notEmpty = function notEmpty() {
var _this2 = this;
if ("production" !== process.env.NODE_ENV) {
this.addCheck(function (path, value) {
if (_this2.isNullable && value === null) {
return;
}
function between$1(state, start, end, options = {}) {
const startDate = createDate(start);
const endDate = createDate(end);
_this2.invariant(value.length > 0, 'Array cannot be empty.', path);
});
}
if (process.env.NODE_ENV !== "production") {
invariant(isValidDate(startDate), 'Between start date must be a valid date.');
}
return this;
};
if (process.env.NODE_ENV !== "production") {
invariant(isValidDate(endDate), 'Between end date must be a valid date.');
}
_proto.typeAlias = function typeAlias() {
var contents = this.contents;
return {
skipIfNull: true,
var alias = _CollectionPredicate.prototype.typeAlias.call(this);
validate(value, path) {
invalid(isValidDate(value) && (options.inclusive ? value >= startDate && value <= endDate : value > startDate && value < endDate), options.message ?? `Date must be between ${startDate.toLocaleDateString()} and ${endDate.toLocaleDateString()}${options.inclusive ? ' inclusive' : ''}.`, path, value);
}
return contents ? alias + "<" + contents.typeAlias() + ">" : alias;
};
return ArrayPredicate;
}(CollectionPredicate);
function array(contents, defaultValue) {
if (contents === void 0) {
contents = null;
}
return new ArrayPredicate(contents, defaultValue);
}
var BooleanPredicate = function (_Predicate) {
_inheritsLoose(BooleanPredicate, _Predicate);
const dateCriteria = /*#__PURE__*/Object.freeze({
__proto__: null,
after: after,
before: before,
between: between$1
});
/**
* Require field value to be between 2 numbers.
*/
function BooleanPredicate(defaultValue) {
return _Predicate.call(this, 'boolean', defaultValue) || this;
function between(state, min, max, options = {}) {
if (process.env.NODE_ENV !== "production") {
invariant(isValidNumber(min) && isValidNumber(max), 'Between requires a minimum and maximum number.');
}
var _proto = BooleanPredicate.prototype;
return {
skipIfNull: true,
_proto.cast = function cast(value) {
return Boolean(value);
};
_proto.onlyFalse = function onlyFalse() {
var _this = this;
this.defaultValue = false;
this.defaultValueFactory = undefined;
if ("production" !== process.env.NODE_ENV) {
this.addCheck(function (path, value) {
_this.invariant(value === false, 'May only be `false`.', path);
});
validate(value, path) {
invalid(isValidNumber(value) && (options.inclusive ? value >= min && value <= max : value > min && value < max), options.message ?? `Number must be between ${min} and ${max}${options.inclusive ? ' inclusive' : ''}.`, path, value);
}
return this;
};
}
/**
* Require field value to be a float (includes a decimal).
*/
_proto.onlyTrue = function onlyTrue() {
var _this2 = this;
this.defaultValue = true;
this.defaultValueFactory = undefined;
function float(state, options = {}) {
return {
skipIfNull: true,
if ("production" !== process.env.NODE_ENV) {
this.addCheck(function (path, value) {
_this2.invariant(value === true, 'May only be `true`.', path);
});
validate(value, path) {
invalid(isValidNumber(value) && value % 1 !== 0, options.message ?? 'Number must be a float.', path, value);
}
return this;
};
return BooleanPredicate;
}(Predicate);
function bool(defaultValue) {
if (defaultValue === void 0) {
defaultValue = false;
}
return new BooleanPredicate(defaultValue);
}
/**
* Require field value to be greater than a number.
*/
function instanceOf(object, contract) {
if (!object || typeof object !== 'object') {
return false;
}
if (object instanceof contract) {
return true;
function gt(state, min, options = {}) {
if (process.env.NODE_ENV !== "production") {
invariant(isValidNumber(min), 'Greater-than requires a minimum number.');
}
var current = object;
return {
skipIfNull: true,
while (current) {
if (current.constructor.name === 'Object') {
return false;
validate(value, path) {
if (options.inclusive) {
invalid(isValidNumber(value) && value >= min, options.message ?? `Number must be greater than or equal to ${min}.`, path, value);
} else {
invalid(isValidNumber(value) && value > min, options.message ?? `Number must be greater than ${min}.`, path, value);
}
}
if (current.constructor.name === contract.name || current instanceof Error && current.name === contract.name) {
return true;
}
};
}
/**
* Require field value to be greater than or equals to a number.
*/
current = Object.getPrototypeOf(current);
}
return false;
function gte(state, min, options = {}) {
return gt(state, min, { ...options,
inclusive: true
});
}
/**
* Require field value to be an integer.
*/
var InstancePredicate = function (_Predicate) {
_inheritsLoose(InstancePredicate, _Predicate);
function InstancePredicate(refClass, loose) {
var _this;
function int(state, options = {}) {
return {
skipIfNull: true,
if (refClass === void 0) {
refClass = null;
validate(value, path) {
invalid(Number.isSafeInteger(value), options.message ?? 'Number must be an integer.', path, value);
}
if (loose === void 0) {
loose = false;
}
};
}
/**
* Require field value to be less than a number.
*/
_this = _Predicate.call(this, 'instance', null) || this;
_this.loose = false;
_this.refClass = null;
_this.nullable();
function lt(state, max, options = {}) {
if (process.env.NODE_ENV !== "production") {
invariant(isValidNumber(max), 'Less-than requires a maximum number.');
}
if ("production" !== process.env.NODE_ENV) {
if (refClass) {
_this.invariant(typeof refClass === 'function', 'A class reference is required.');
return {
skipIfNull: true,
validate(value, path) {
if (options.inclusive) {
invalid(isValidNumber(value) && value <= max, options.message ?? `Number must be less than or equal to ${max}.`, path, value);
} else {
invalid(isValidNumber(value) && value < max, options.message ?? `Number must be less than ${max}.`, path, value);
}
}
_this.loose = loose;
_this.refClass = refClass;
};
}
/**
* Require field value to be less than or equals to a number.
*/
_this.addCheck(function (path, value) {
if (refClass) {
_this.invariant(typeof refClass === 'function' && (value instanceof refClass || _this.loose && isObject(value) && instanceOf(value, refClass)), "Must be an instance of \"" + _this.typeAlias() + "\".", path);
} else {
_this.invariant(isObject(value) && value.constructor.name !== 'Object', 'Must be a class instance.', path);
}
});
}
return _this;
}
function lte(state, max, options = {}) {
return lt(state, max, { ...options,
inclusive: true
});
}
/**
* Require field value to be negative and not zero.
*/
var _proto = InstancePredicate.prototype;
_proto.typeAlias = function typeAlias() {
var refClass = this.refClass;
return refClass ? refClass.name || refClass.constructor.name : 'class';
};
function negative(state, options = {}) {
return {
skipIfNull: true,
return InstancePredicate;
}(Predicate);
function instance(refClass, loose) {
if (refClass === void 0) {
refClass = null;
}
validate(value, path) {
invalid(isValidNumber(value) && value < 0, options.message ?? 'Number must be negative.', path, value);
}
return new InstancePredicate(refClass, loose);
};
}
function predicate() {
return instance(Predicate);
}
function regex() {
return instance(RegExp);
}
function date() {
return instance(Date);
}
/**
* Require field value to be one of the provided numbers.
*/
function isNumber(value) {
return typeof value === 'number' && !Number.isNaN(value);
}
var NumberPredicate = function (_Predicate) {
_inheritsLoose(NumberPredicate, _Predicate);
function NumberPredicate(defaultValue) {
return _Predicate.call(this, 'number', defaultValue) || this;
function oneOf$1(state, list, options = {}) {
if (process.env.NODE_ENV !== "production") {
invariant(Array.isArray(list) && list.length > 0 && list.every(item => isValidNumber(item)), 'One of requires an array of numbers.');
}
var _proto = NumberPredicate.prototype;
return {
skipIfNull: true,
_proto.between = function between(min, max, inclusive) {
var _this = this;
if (inclusive === void 0) {
inclusive = false;
validate(value, path) {
invalid(list.includes(value), options.message ?? `Number must be one of: ${list.join(', ')}`, path, value);
}
if ("production" !== process.env.NODE_ENV) {
this.invariant(isNumber(min) && isNumber(max), 'Between requires a minimum and maximum number.');
this.addCheck(function (path, value) {
_this.invariant(isNumber(value) && (inclusive ? value >= min && value <= max : value > min && value < max), "Number must be between " + min + " and " + max + (inclusive ? ' inclusive' : '') + ".", path);
});
}
return this;
};
}
/**
* Require field value to be positive and not zero.
*/
_proto.cast = function cast(value) {
return value === undefined ? 0 : Number(value);
};
_proto.float = function float() {
var _this2 = this;
function positive(state, options = {}) {
return {
skipIfNull: true,
if ("production" !== process.env.NODE_ENV) {
this.addCheck(function (path, value) {
_this2.invariant(isNumber(value) && value % 1 !== 0, 'Number must be a float.', path);
});
validate(value, path) {
invalid(isValidNumber(value) && value > 0, options.message ?? 'Number must be positive.', path, value);
}
return this;
};
}
_proto.gt = function gt(min, inclusive) {
var _this3 = this;
const numberCriteria = /*#__PURE__*/Object.freeze({
__proto__: null,
between: between,
float: float,
gt: gt,
gte: gte,
int: int,
lt: lt,
lte: lte,
negative: negative,
oneOf: oneOf$1,
positive: positive
});
/**
* Require field object keys to be of a string schema type.
*/
if (inclusive === void 0) {
inclusive = false;
}
function keysOf(state, keysSchema, options = {}) {
if (process.env.NODE_ENV !== "production") {
invariant(isSchema(keysSchema) && keysSchema.schema() === 'string', 'A string schema is required for object keys.');
}
if ("production" !== process.env.NODE_ENV) {
this.invariant(isNumber(min), 'Greater-than requires a minimum number.');
this.addCheck(function (path, value) {
if (inclusive) {
_this3.invariant(isNumber(value) && value >= min, "Number must be greater than or equal to " + min + ".", path);
} else {
_this3.invariant(isNumber(value) && value > min, "Number must be greater than " + min + ".", path);
}
});
return {
skipIfNull: true,
validate(value, path, validateOptions) {
if (isObject(value)) {
Object.keys(value).forEach(key => {
try {
// Dont pass path so its not included in the error message
keysSchema.validate(key, '', validateOptions);
} catch (error) {
if (error instanceof Error) {
invalid(false, `Invalid key "${key}". ${options.message ?? error.message}`, path, value);
}
}
});
}
}
return this;
};
}
/**
* Require field object to not be empty.
*/
_proto.gte = function gte(min) {
return this.gt(min, true);
};
_proto.int = function int() {
var _this4 = this;
function notEmpty$1(state, options = {}) {
return {
skipIfNull: true,
if ("production" !== process.env.NODE_ENV) {
this.addCheck(function (path, value) {
_this4.invariant(Number.isSafeInteger(value), 'Number must be an integer.', path);
});
validate(value, path) {
invalid(Object.keys(value).length > 0, options.message ?? 'Object cannot be empty.', path, value);
}
return this;
};
}
/**
* Require field object values to be of a specific schema type.
* Will rebuild the object and type cast values.
*/
_proto.lt = function lt(max, inclusive) {
var _this5 = this;
if (inclusive === void 0) {
inclusive = false;
}
function of$3(state, valuesSchema) {
if (process.env.NODE_ENV !== "production") {
invariant(isSchema(valuesSchema), 'A schema is required for object values.');
}
if ("production" !== process.env.NODE_ENV) {
this.invariant(isNumber(max), 'Less-than requires a maximum number.');
this.addCheck(function (path, value) {
if (inclusive) {
_this5.invariant(isNumber(value) && value <= max, "Number must be less than or equal to " + max + ".", path);
} else {
_this5.invariant(isNumber(value) && value < max, "Number must be less than " + max + ".", path);
}
state.type += `<${valuesSchema.type()}>`;
return {
skipIfNull: true,
validate(value, path, validateOptions) {
if (!isObject(value)) {
return {};
}
const nextValue = { ...value
};
Object.keys(value).forEach(baseKey => {
const key = baseKey;
nextValue[key] = valuesSchema.validate(value[key], path ? `${path}.${key}` : String(key), validateOptions);
});
return nextValue;
}
return this;
};
}
/**
* Require field object to be of a specific size.
*/
_proto.lte = function lte(max) {
return this.lt(max, true);
};
_proto.negative = function negative() {
var _this6 = this;
function sizeOf$1(state, size, options = {}) {
if (process.env.NODE_ENV !== "production") {
invariant(typeof size === 'number' && size > 0, 'Size of requires a non-zero positive number.');
}
if ("production" !== process.env.NODE_ENV) {
this.addCheck(function (path, value) {
_this6.invariant(isNumber(value) && value < 0, 'Number must be negative.', path);
});
return {
skipIfNull: true,
validate(value, path) {
invalid(Object.keys(value).length === size, options.message ?? (size === 1 ? `Object must have ${size} property.` : `Object must have ${size} properties.`), path, value);
}
return this;
};
}
_proto.oneOf = function oneOf(list) {
var _this7 = this;
const objectCriteria = /*#__PURE__*/Object.freeze({
__proto__: null,
keysOf: keysOf,
notEmpty: notEmpty$1,
of: of$3,
sizeOf: sizeOf$1
});
/**
* Require a shape to be an exact shape.
* No more and no less of the same properties.
*/
if ("production" !== process.env.NODE_ENV) {
this.invariant(Array.isArray(list) && list.length > 0 && list.every(function (item) {
return isNumber(item);
}), 'One of requires a non-empty array of numbers.');
this.addCheck(function (path, value) {
_this7.invariant(list.includes(value), "Number must be one of: " + list.join(', '), path);
});
}
function exact(state, value = true) {
state.metadata.exact = value;
}
/**
* Require field to be an object with every property being a schema type.
* Will rebuild the object (if not a class instance) and type cast values.
*/
return this;
};
_proto.positive = function positive() {
var _this8 = this;
function of$2(state, schemas) {
if (process.env.NODE_ENV !== "production") {
invariant(isObject(schemas) && Object.keys(schemas).length > 0 && Object.values(schemas).every(isSchema), 'A non-empty object of schemas are required for a shape.');
}
if ("production" !== process.env.NODE_ENV) {
this.addCheck(function (path, value) {
_this8.invariant(isNumber(value) && value > 0, 'Number must be positive.', path);
const types = Object.entries(schemas).map(([key, value]) => `${key}: ${value.type()}`);
state.type += `<{ ${types.join(', ')} }>`;
return {
skipIfNull: true,
validate(value, path, validateOptions) {
if (value) {
invalid(isObject(value), 'Value passed to shape must be an object.', path, value);
}
const isPlainObject = value.constructor === Object;
const unknown = isPlainObject ? { ...value
} : {};
const shape = {};
const collectionError = new ValidationError('The following validations have failed:', path, value);
Object.keys(schemas).forEach(prop => {
const key = prop;
const schema = schemas[key];
tryAndCollect(() => {
shape[key] = schema.validate(value[key], path ? `${path}.${key}` : String(key), { ...validateOptions,
currentObject: value
});
}, collectionError, validateOptions.collectErrors); // Delete the prop and mark it as known
delete unknown[key];
});
}
return this;
};
if (collectionError.errors.length > 0) {
throw collectionError;
} // Handle unknown fields
return NumberPredicate;
}(Predicate);
function number(defaultValue) {
return new NumberPredicate(defaultValue);
}
var ObjectPredicate = function (_CollectionPredicate) {
_inheritsLoose(ObjectPredicate, _CollectionPredicate);
if (state.metadata.exact) {
if (process.env.NODE_ENV !== "production") {
logUnknown(unknown, path);
}
} else {
Object.assign(shape, unknown);
} // Dont replace class instance with plain objects
function ObjectPredicate(contents, defaultValue) {
var _this;
if (contents === void 0) {
contents = null;
return isPlainObject ? shape : value;
}
_this = _CollectionPredicate.call(this, 'object', defaultValue) || this;
_this.contents = null;
_this.contents = contents;
};
}
if (contents instanceof Predicate) {
_this.addCheck(function (path, value) {
var nextValue = _extends({}, value);
const shapeCriteria = /*#__PURE__*/Object.freeze({
__proto__: null,
exact: exact,
of: of$2
});
/**
* Require field value to contain a provided string.
*/
Object.keys(value).forEach(function (baseKey) {
var key = baseKey;
nextValue[key] = contents.run(value[key], path + "." + key, _this.schema);
});
return nextValue;
});
} else if ("production" !== process.env.NODE_ENV && contents) {
_this.invariant(false, 'A blueprint is required for object contents.');
}
return _this;
function contains(state, token, options = {}) {
if (process.env.NODE_ENV !== "production") {
invariant(isValidString(token), 'Contains requires a non-empty token.');
}
var _proto = ObjectPredicate.prototype;
return {
skipIfNull: true,
skipIfOptional: true,
_proto.cast = function cast(value) {
var obj = isObject(value) ? value : {};
return obj;
validate(value, path) {
invalid(value.includes(token, options.index ?? 0), options.message ?? `String does not include "${token}".`, path, value);
}
};
}
/**
* Require field value to match a defined regex pattern.
*/
_proto.notEmpty = function notEmpty() {
var _this2 = this;
if ("production" !== process.env.NODE_ENV) {
this.addCheck(function (path, value) {
if (_this2.isNullable && value === null) {
return;
}
function match(state, pattern, options = {}) {
if (process.env.NODE_ENV !== "production") {
invariant(pattern instanceof RegExp, 'Match requires a regular expression to match against.');
}
_this2.invariant(Object.keys(value).length > 0, 'Object cannot be empty.', path);
});
return {
skipIfNull: true,
skipIfOptional: true,
validate(value, path) {
invalid(!!value.match(pattern), `${options.message ?? 'String does not match.'} (pattern "${pattern.source}")`, path, value);
}
return this;
};
}
/**
* Require field value to be formatted in camel case (fooBar).
*/
_proto.typeAlias = function typeAlias() {
var contents = this.contents;
var alias = _CollectionPredicate.prototype.typeAlias.call(this);
function camelCase(state, options = {}) {
return match(state, /^[a-z][a-zA-Z0-9]+$/u, {
message: 'String must be in camel case.',
...options
});
}
/**
* Require field value to be formatted in kebab case (foo-bar).
*/
return contents ? alias + "<" + contents.typeAlias() + ">" : alias;
};
return ObjectPredicate;
}(CollectionPredicate);
function object(contents, defaultValue) {
if (contents === void 0) {
contents = null;
}
function kebabCase(state, options = {}) {
return match(state, /^[a-z][a-z0-9-]+$/u, {
message: 'String must be in kebab case.',
...options
});
}
/**
* Require field value to be formatted in pascal case (FooBar).
*/
return new ObjectPredicate(contents, defaultValue);
function pascalCase(state, options = {}) {
return match(state, /^[A-Z][a-zA-Z0-9]+$/u, {
message: 'String must be in pascal case.',
...options
});
}
function blueprint(defaultValue) {
return new ObjectPredicate(predicate().notNullable(), defaultValue);
/**
* Require field value to be formatted in snake case (foo_bar).
*/
function snakeCase(state, options = {}) {
return match(state, /^[a-z][a-z0-9_]+$/u, {
message: 'String must be in snake case.',
...options
});
}
/**
* Require field value to not be an empty string.
*/
var ShapePredicate = function (_Predicate) {
_inheritsLoose(ShapePredicate, _Predicate);
function ShapePredicate(contents) {
var _this;
function notEmpty(state, options = {}) {
return {
skipIfNull: true,
_this = _Predicate.call(this, 'shape', {}) || this;
_this.contents = void 0;
_this.isExact = false;
if ("production" !== process.env.NODE_ENV) {
_this.invariant(isObject(contents) && Object.keys(contents).length > 0 && Object.values(contents).every(function (content) {
return content instanceof Predicate;
}), 'A non-empty object of properties to blueprints are required for a shape.');
validate(value, path) {
invalid(isValidString(value), options.message ?? 'String cannot be empty.', path, value);
}
_this.contents = contents;
return _this;
};
}
/**
* Require field value to be one of the provided string.
*/
function oneOf(state, list, options = {}) {
if (process.env.NODE_ENV !== "production") {
invariant(Array.isArray(list) && list.length > 0 && list.every(item => typeof item === 'string'), 'One of requires an array of strings.');
}
var _proto = ShapePredicate.prototype;
return {
skipIfNull: true,
_proto.default = function _default() {
var _this2 = this;
validate(value, path) {
invalid(list.includes(value), options.message ?? `String must be one of: ${list.join(', ')}`, path, value);
}
var struct = {};
Object.keys(this.contents).forEach(function (baseKey) {
var key = baseKey;
struct[key] = _this2.contents[key].default();
});
return struct;
};
}
/**
* Require field value to be all lower case.
*/
_proto.exact = function exact() {
this.isExact = true;
return this;
};
_proto.doRun = function doRun(value, path) {
var _this$schema,
_this$schema2,
_this3 = this;
function lowerCase(state, options = {}) {
return {
skipIfNull: true,
if ("production" !== process.env.NODE_ENV && value) {
this.invariant(isObject(value), 'Value passed to shape must be an object.', path);
validate(value, path) {
invalid(value === value.toLocaleLowerCase(), options.message ?? 'String must be lower cased.', path, value);
}
var unknownFields = _extends({}, value);
};
}
/**
* Require field value to be all upper case.
*/
var struct = _extends({}, value);
var oldPath = (_this$schema = this.schema) == null ? void 0 : _this$schema.parentPath;
var oldStruct = (_this$schema2 = this.schema) == null ? void 0 : _this$schema2.parentStruct;
this.schema.parentPath = path;
this.schema.parentStruct = struct;
Object.keys(this.contents).forEach(function (baseKey) {
var key = baseKey;
var content = _this3.contents[key];
struct[key] = content.run(value == null ? void 0 : value[key], path + "." + key, _this3.schema);
delete unknownFields[key];
});
function upperCase(state, options = {}) {
return {
skipIfNull: true,
if (this.isExact) {
if ("production" !== process.env.NODE_ENV) {
logUnknown(unknownFields, path);
}
} else {
Object.assign(struct, unknownFields);
validate(value, path) {
invalid(value === value.toLocaleUpperCase(), options.message ?? 'String must be upper cased.', path, value);
}
this.schema.parentPath = oldPath;
this.schema.parentStruct = oldStruct;
return struct;
};
return ShapePredicate;
}(Predicate);
function shape(contents) {
return new ShapePredicate(contents);
}
/**
* Require field array to be of a specific size.
*/
function isString(value) {
return typeof value === 'string' && value !== '';
}
var StringPredicate = function (_CollectionPredicate) {
_inheritsLoose(StringPredicate, _CollectionPredicate);
function StringPredicate(defaultValue) {
return _CollectionPredicate.call(this, 'string', defaultValue) || this;
function sizeOf(state, size, options = {}) {
if (process.env.NODE_ENV !== "production") {
invariant(typeof size === 'number' && size > 0, 'Size requires a non-zero positive number.');
}
var _proto = StringPredicate.prototype;
return {
skipIfNull: true,
_proto.camelCase = function camelCase() {
return this.match(/^[a-z][0-9A-Za-z]+$/, 'String must be in camel case.');
};
validate(value, path) {
invalid(value.length === size, options.message ?? `String length must be ${size}.`, path, value);
}
_proto.cast = function cast(value) {
return value === undefined ? '' : String(value);
};
}
_proto.contains = function contains(token, index) {
var _this = this;
const stringCriteria = /*#__PURE__*/Object.freeze({
__proto__: null,
contains: contains,
match: match,
camelCase: camelCase,
kebabCase: kebabCase,
pascalCase: pascalCase,
snakeCase: snakeCase,
notEmpty: notEmpty,
oneOf: oneOf,
lowerCase: lowerCase,
upperCase: upperCase,
sizeOf: sizeOf
});
/**
* Require field array items to be of a specific schema type.
* Will rebuild the array and type cast values.
*/
if (index === void 0) {
index = 0;
}
function of$1(state, itemsSchemas) {
if (process.env.NODE_ENV !== "production") {
invariant(Array.isArray(itemsSchemas) && itemsSchemas.length > 0 && itemsSchemas.every(isSchema), 'A non-empty array of schemas are required for a tuple.');
}
if ("production" !== process.env.NODE_ENV) {
this.invariant(isString(token), 'Contains requires a non-empty token.');
this.addCheck(function (path, value) {
if (_this.isOptionalDefault(value)) {
return;
}
state.type = `tuple<${itemsSchemas.map(item => item.type()).join(', ')}>`;
return {
skipIfNull: true,
_this.invariant(value.includes(token, index), "String does not include \"" + token + "\".", path);
});
validate(value, path, validateOptions) {
invalid(Array.isArray(value) && value.length <= itemsSchemas.length, `Value must be a tuple with ${itemsSchemas.length} items.`, path, value);
return itemsSchemas.map((item, i) => item.validate(value[i], `${path}[${i}]`, validateOptions));
}
return this;
};
}
_proto.kebabCase = function kebabCase() {
return this.match(/^[a-z][\x2D0-9a-z]+$/, 'String must be in kebab case.');
};
const tupleCriteria = /*#__PURE__*/Object.freeze({
__proto__: null,
of: of$1
});
_proto.lowerCase = function lowerCase() {
var _this2 = this;
function typeOf(value) {
if (Array.isArray(value)) {
return 'array/tuple';
}
if ("production" !== process.env.NODE_ENV) {
this.addCheck(function (path, value) {
_this2.invariant(value === value.toLocaleLowerCase(), 'String must be lower cased.', path);
});
}
if (isObject(value)) {
return value.constructor === Object ? 'object/shape' : 'class';
}
return this;
};
return typeof value;
}
/**
* Require field value to be one of a specific schema type.
*/
_proto.match = function match(pattern, message) {
var _this3 = this;
if (message === void 0) {
message = '';
}
function of(state, schemas) {
if (process.env.NODE_ENV !== "production") {
invariant(Array.isArray(schemas) && schemas.length > 0 && schemas.every(isSchema), 'A non-empty array of schemas are required for a union.');
}
if ("production" !== process.env.NODE_ENV) {
this.invariant(pattern instanceof RegExp, 'Match requires a regular expression to match against.');
this.addCheck(function (path, value) {
if (_this3.isOptionalDefault(value)) {
return;
state.type = schemas.map(item => item.type()).join(' | ');
return {
skipIfNull: true,
validate(value, path, validateOptions) {
let nextValue = value;
const allowedValues = schemas.map(schema => schema.type()).join(', ');
const valueType = typeOf(value);
const collectionError = new ValidationError(`Received ${valueType} with the following failures:`, path, value);
const passed = schemas.some(schema => {
const schemaType = schema.schema();
if (schemaType === 'union') {
invalid(false, 'Nested unions are not supported.', path);
}
_this3.invariant(!!value.match(pattern), (message || 'String does not match.') + " (pattern \"" + pattern.source + "\")", path);
return tryAndCollect(() => {
if (valueType === schemaType || valueType === 'object/shape' && schemaType === 'object' || valueType === 'object/shape' && schemaType === 'shape' || valueType === 'array/tuple' && schemaType === 'array' || valueType === 'array/tuple' && schemaType === 'tuple' || schemaType === 'custom') {
// Dont pass path so its not included in the error message
nextValue = schema.validate(value, '', validateOptions);
return true;
}
return false;
}, collectionError, validateOptions.collectErrors);
});
if (!passed) {
if (collectionError.errors.length > 0) {
throw collectionError;
} else {
invalid(false, `Value must be one of: ${allowedValues}.`, path, value);
}
}
return nextValue;
}
return this;
};
}
_proto.notEmpty = function notEmpty() {
var _this4 = this;
const unionCriteria = /*#__PURE__*/Object.freeze({
__proto__: null,
of: of
});
if ("production" !== process.env.NODE_ENV) {
this.addCheck(function (path, value) {
if (_this4.isNullable && value === null) {
return;
}
function array(defaultValue = []) {
return createSchema({
api: { ...commonCriteria,
...arrayCriteria
},
cast: createArray,
defaultValue,
type: 'array'
}, [{
skipIfNull: true,
_this4.invariant(isString(value), 'String cannot be empty.', path);
});
validate(value, path) {
invalid(Array.isArray(value), 'Must be an array.', path, value);
}
return this;
};
}]);
}
_proto.oneOf = function oneOf(list) {
var _this5 = this;
function object(defaultValue) {
return createSchema({
api: { ...commonCriteria,
...objectCriteria
},
cast: createObject,
defaultValue: defaultValue ?? {},
type: 'object'
}, [{
skipIfNull: true,
if ("production" !== process.env.NODE_ENV) {
this.invariant(Array.isArray(list) && list.length > 0 && list.every(function (item) {
return isString(item);
}), 'One of requires a non-empty array of strings.');
this.addCheck(function (path, value) {
_this5.invariant(list.includes(value), "String must be one of: " + list.join(', '), path);
});
validate(value, path) {
invalid(isObject(value), 'Must be a plain object.', path, value);
}
return this;
};
}]);
} // eslint-disable-next-line @typescript-eslint/no-explicit-any
_proto.pascalCase = function pascalCase() {
return this.match(/^[A-Z][0-9A-Za-z]+$/, 'String must be in pascal case.');
};
_proto.snakeCase = function snakeCase() {
return this.match(/^[a-z][0-9_a-z]+$/, 'String must be in snake case.');
};
function func(defaultValue) {
return createSchema({
api: { ...commonCriteria
},
defaultValue,
type: 'function'
}, [{
skipIfNull: true,
skipIfOptional: true,
_proto.upperCase = function upperCase() {
var _this6 = this;
validate(value, path) {
invalid(typeof value === 'function', 'Must be a function.', path, value);
}
if ("production" !== process.env.NODE_ENV) {
this.addCheck(function (path, value) {
_this6.invariant(value === value.toLocaleUpperCase(), 'String must be upper cased.', path);
});
}]);
} // This is similar to shape, but we want to control the validation
function schema() {
const shape = createSchema({
api: { ...commonCriteria,
...shapeCriteria
},
cast: createObject,
type: 'shape'
}, [{
skipIfNull: true,
validate(value, path) {
invalid(isObject(value), 'Must be a schema.', path, value);
}
return this;
};
}]);
return shape.of({
schema: func().notNullable().required(),
type: func().notNullable().required(),
validate: func().notNullable().required()
});
}
return StringPredicate;
}(CollectionPredicate);
function string(defaultValue) {
return new StringPredicate(defaultValue);
function blueprint(defaultValue)
/* infer */
{
return object(defaultValue).of(schema().notNullable());
}
var TuplePredicate = function (_Predicate) {
_inheritsLoose(TuplePredicate, _Predicate);
function bool(defaultValue = false) {
return createSchema({
api: { ...commonCriteria,
...booleanCriteria
},
cast: Boolean,
defaultValue,
type: 'boolean'
}, [{
skipIfNull: true,
function TuplePredicate(contents) {
var _this;
validate(value, path) {
invalid(typeof value === 'boolean', 'Must be a boolean.', path, value);
}
_this = _Predicate.call(this, 'tuple', []) || this;
_this.contents = void 0;
}]);
}
if ("production" !== process.env.NODE_ENV) {
_this.invariant(Array.isArray(contents) && contents.length > 0 && contents.every(function (content) {
return content instanceof Predicate;
}), 'A non-empty array of blueprints are required for a tuple.');
function custom(validator, defaultValue) {
return createSchema({
api: { ...commonCriteria
},
defaultValue,
type: 'custom'
}).custom(validator);
}
function date(defaultValue) {
return createSchema({
api: { ...commonCriteria,
...dateCriteria
},
cast: createDate,
defaultValue: defaultValue ?? new Date(),
type: 'date'
}, [{
skipIfNull: true,
validate(value, path) {
const time = createDate(value);
invalid(isValidDate(time), 'Must be a string, number, or `Date` that resolves to a valid date.', path, value);
return time;
}
_this.contents = contents;
return _this;
}
}]);
}
var _proto = TuplePredicate.prototype;
function instance() {
return createSchema({
api: { ...commonCriteria,
...classCriteria
},
defaultValue: null,
type: 'class'
}, [state => ({
skipIfNull: true,
_proto.default = function _default() {
return this.contents.map(function (content) {
return content.default();
});
};
validate(value, path) {
invalid(isObject(value) && value.constructor !== Object, state.type === 'class' ? 'Must be a class instance.' : `Must be an instance of ${state.type}.`, path, value);
}
_proto.typeAlias = function typeAlias() {
return "tuple<" + this.contents.map(function (item) {
return item.typeAlias();
}).join(', ') + ">";
};
})]).nullable();
}
_proto.doRun = function doRun(value, path) {
var _this2 = this;
function lazy(factory, defaultValue) {
if (process.env.NODE_ENV !== "production") {
invariant(typeof factory === 'function', 'Lazy requires a schema factory function.');
}
if ("production" !== process.env.NODE_ENV) {
if (value) {
this.invariant(Array.isArray(value) && value.length <= this.contents.length, "Value must be a tuple with less than or equal to " + this.contents.length + " items.");
return createSchema({
api: { ...commonCriteria
},
defaultValue,
type: 'lazy'
}, [{
// Avoid recursion by returning early and using the provided default value
skipIfNull: true,
skipIfOptional: true,
validate(value, path, validateOptions) {
const schema = factory(value);
if (process.env.NODE_ENV !== "production") {
invariant(isSchema(schema), 'Factory must return a schema.');
}
return schema.validate(value, path, validateOptions);
}
var nextValue = value ? [].concat(value) : [];
this.contents.forEach(function (content, i) {
nextValue[i] = content.run(nextValue[i], path + "[" + i + "]", _this2.schema);
});
return nextValue;
};
}]);
}
return TuplePredicate;
}(Predicate);
function tuple(contents) {
return new TuplePredicate(contents);
function cast$1(value) {
return value === undefined ? 0 : Number(value);
}
var UnionPredicate = function (_Predicate) {
_inheritsLoose(UnionPredicate, _Predicate);
function number(defaultValue = 0) {
return createSchema({
api: { ...commonCriteria,
...numberCriteria
},
cast: cast$1,
defaultValue,
type: 'number'
}, [{
skipIfNull: true,
function UnionPredicate(contents, defaultValue) {
var _this;
validate(value, path) {
invalid(typeof value === 'number', 'Must be a number.', path, value);
}
_this = _Predicate.call(this, 'union', defaultValue) || this;
_this.contents = [];
}]);
}
if ("production" !== process.env.NODE_ENV) {
_this.invariant(Array.isArray(contents) && contents.length > 0 && contents.every(function (content) {
return content instanceof Predicate;
}), 'A non-empty array of blueprints are required for a union.');
function regex()
/* infer */
{
return instance().of(RegExp);
}
_this.addCheck(_this.checkUnions);
}
function shape(blueprint) {
return createSchema({
api: { ...commonCriteria,
...shapeCriteria
},
cast: createObject,
type: 'shape'
}, [{
skipIfNull: true,
_this.contents = contents;
return _this;
}
validate(value, path) {
if (value === undefined) {
// Will be built from its items
return {};
}
var _proto = UnionPredicate.prototype;
invalid(isObject(value), 'Must be a shaped object.', path, value);
return value;
}
_proto.typeAlias = function typeAlias() {
return this.contents.map(function (content) {
return content.typeAlias();
}).join(' | ');
};
}]).of(blueprint);
}
_proto.checkUnions = function checkUnions(path, value) {
var _this2 = this;
function cast(value) {
return value === undefined ? '' : String(value);
}
var nextValue = value;
function string(defaultValue = '') {
return createSchema({
api: { ...commonCriteria,
...stringCriteria
},
cast,
defaultValue,
type: 'string'
}, [{
skipIfNull: true,
if ("production" !== process.env.NODE_ENV) {
var contents = this.contents;
var keys = contents.map(function (content) {
return content.typeAlias();
}).join(', ');
var type = typeOf(value);
var errors = new Set();
var passed = contents.some(function (content) {
if (content.type === 'union') {
_this2.invariant(false, 'Nested unions are not supported.', path);
}
validate(value, path) {
invalid(typeof value === 'string', 'Must be a string.', path, value);
}
try {
if (type === content.type || type === 'object' && content.type === 'shape' || type === 'array' && content.type === 'tuple' || content.type === 'custom') {
content.noErrorPrefix = true;
nextValue = content.run(value, path, _this2.schema);
return true;
}
} catch (error) {
errors.add("\n - " + error.message);
}
}]);
}
return false;
});
var displayValue = this.extractDisplayValue(value);
var message = contents.length === 1 ? "Received " + displayValue + " but must be: " + keys : "Received " + displayValue + " but must be a union of: " + keys;
function tuple(schemas) {
return createSchema({
api: { ...commonCriteria,
...tupleCriteria
},
// @ts-expect-error Ignore this, it's safe
cast: createArray,
type: 'tuple'
}, [{
skipIfNull: true,
if (!passed && errors.size > 0) {
errors.forEach(function (error) {
message += error;
});
validate(value, path) {
if (value === undefined) {
// Will be built from its items
return [];
}
this.invariant(passed, message.trim(), path);
invalid(Array.isArray(value), 'Must be a tuple.', path, value);
return value;
}
return nextValue;
};
}]).of(schemas);
}
return UnionPredicate;
}(Predicate);
function union(contents, defaultValue) {
return new UnionPredicate(contents, defaultValue);
function union(defaultValue) {
return createSchema({
api: { ...commonCriteria,
...unionCriteria
},
defaultValue,
type: 'union'
});
}
/**
* @copyright 2017-2019, Miles Johnson
* @license https://opensource.org/licenses/MIT
*/
var predicates = {
const index = /*#__PURE__*/Object.freeze({
__proto__: null,
array: array,

@@ -1400,6 +1638,7 @@ blueprint: blueprint,

instance: instance,
lazy: lazy,
number: number,
object: object,
predicate: predicate,
regex: regex,
schema: schema,
shape: shape,

@@ -1409,5 +1648,69 @@ string: string,

union: union
};
});
export default optimal;
export { ArrayPredicate, BooleanPredicate, InstancePredicate, NumberPredicate, ObjectPredicate, Predicate, Schema, ShapePredicate, StringPredicate, TuplePredicate, UnionPredicate, array, blueprint, bool, custom, date, func, instance, number, object, predicate, predicates, regex, shape, string, tuple, union };
function createPredicate(schema) {
return value => {
try {
schema.validate(value);
} catch {
return false;
}
return true;
};
}
function optimal(blueprint, baseOpts = {}) {
const options = {};
let schema = shape(blueprint);
function configure(nextOpts) {
if (!isObject(nextOpts)) {
throw new TypeError('Optimal options must be a plain object.');
}
Object.assign(options, nextOpts);
schema = schema.exact(!options.unknown);
}
configure(baseOpts);
return {
configure,
validate(struct, validateOptions) {
const object = struct;
try {
return schema.validate(struct, options.prefix ?? '', {
collectErrors: true,
...validateOptions,
currentObject: object,
rootObject: object
});
} catch (error) {
let invalid;
if (error instanceof OptimalError) {
invalid = error;
} else {
invalid = new OptimalError();
invalid.addError(error);
}
if (options.name) {
invalid.schema = options.name;
}
if (options.file) {
invalid.file = options.file;
}
throw invalid;
}
}
};
}
export { OptimalError, ValidationError, array, arrayCriteria, blueprint, bool, booleanCriteria, classCriteria, commonCriteria, createPredicate, createSchema, custom, date, dateCriteria, func, instance, lazy, number, numberCriteria, object, objectCriteria, optimal, regex, schema, index as schemas, shape, shapeCriteria, string, stringCriteria, tuple, tupleCriteria, union, unionCriteria };
//# sourceMappingURL=index.js.map
{
"name": "optimal",
"version": "4.3.0",
"description": "A system for building and validating defined object structures.",
"main": "./lib/index.js",
"type": "module",
"version": "5.0.0-alpha.1",
"description": "A system for building and validating defined object structures with schemas.",
"main": "./mjs/index.mjs",
"module": "./esm/index.js",
"types": "./lib/index.d.ts",
"scripts": {
"prepare": "beemo create-config --silent",
"build": "beemo create-config babel --esm --silent && rollup --config && beemo typescript --emitDeclarationOnly",
"coverage": "yarn run jest --coverage",
"eslint": "beemo eslint",
"jest": "beemo jest",
"prettier": "beemo prettier",
"prerelease": "yarn test && yarn run build",
"release": "npx np --yolo --no-yarn",
"pretest": "yarn run type",
"test": "yarn run jest",
"posttest": "yarn run eslint",
"type": "beemo typescript --noEmit"
},
"repository": {
"type": "git",
"url": "git+https://github.com/milesj/optimal.git"
},
"types": "./dts/index.d.ts",
"keywords": [
"opts",
"options",
"schema",
"predicate",

@@ -37,2 +21,7 @@ "validator",

],
"repository": {
"type": "git",
"url": "git@github.com:milesj/optimal.git",
"directory": "optimal"
},
"author": {

@@ -43,40 +32,44 @@ "name": "Miles Johnson",

"license": "MIT",
"bugs": {
"url": "https://github.com/milesj/optimal/issues"
},
"homepage": "https://github.com/milesj/optimal#readme",
"files": [
"dts/**/*.d.ts",
"esm/**/*.{js,map}",
"mjs/**/*.{js,map}",
"mjs/**/*.{mjs,map}",
"src/**/*.{ts,tsx,json}"
],
"engines": {
"node": ">=10.10.0"
"node": ">=12.17.0",
"npm": ">=6.13.0"
},
"funding": {
"type": "ko-fi",
"url": "https://ko-fi.com/milesjohnson"
},
"packemon": {
"bundle": true,
"format": [
"mjs",
"esm"
],
"platform": [
"browser",
"node"
]
},
"devDependencies": {
"@milesj/build-tools": "^2.17.1",
"@types/node": "^14.14.31",
"conventional-changelog-beemo": "^2.1.0",
"rollup": "^2.39.0",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-node-resolve": "^5.2.0"
"@jest/globals": "*"
},
"beemo": {
"module": "@milesj/build-tools",
"drivers": [
"babel",
"eslint",
"jest",
"prettier",
"typescript"
],
"eslint": {
"rules": {
"default-param-last": "off",
"no-param-reassign": "off"
}
"exports": {
"./package.json": "./package.json",
".": {
"browser": {
"import": "./esm/index.js",
"module": "./esm/index.js"
},
"node": {
"import": "./mjs/index.mjs"
},
"types": "./dts/index.d.ts"
}
},
"browserslist": [
"ie 11"
],
"funding": {
"type": "ko-fi",
"url": "https://ko-fi.com/milesjohnson"
}
}

@@ -26,4 +26,4 @@ # Optimal

name: string().notEmpty(),
include: array(string()),
exclude: array(string()),
include: array().of(string()),
exclude: array().of(string()),
maxSize: number(10000).gte(0),

@@ -44,4 +44,4 @@ },

- Node 10 (server)
- IE 11+ (browser)
- Node 12.17+
- Edge / Modern browsers

@@ -48,0 +48,0 @@ ## Installation

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc