'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var propertyExpr = require('property-expr'); var tinyCase = require('tiny-case'); var toposort = require('toposort'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var toposort__default = /*#__PURE__*/_interopDefaultLegacy(toposort); const toString = Object.prototype.toString; const errorToString = Error.prototype.toString; const regExpToString = RegExp.prototype.toString; const symbolToString = typeof Symbol !== 'undefined' ? Symbol.prototype.toString : () => ''; const SYMBOL_REGEXP = /^Symbol\((.*)\)(.*)$/; function printNumber(val) { if (val != +val) return 'NaN'; const isNegativeZero = val === 0 && 1 / val < 0; return isNegativeZero ? '-0' : '' + val; } function printSimpleValue(val, quoteStrings = false) { if (val == null || val === true || val === false) return '' + val; const typeOf = typeof val; if (typeOf === 'number') return printNumber(val); if (typeOf === 'string') return quoteStrings ? `"${val}"` : val; if (typeOf === 'function') return '[Function ' + (val.name || 'anonymous') + ']'; if (typeOf === 'symbol') return symbolToString.call(val).replace(SYMBOL_REGEXP, 'Symbol($1)'); const tag = toString.call(val).slice(8, -1); if (tag === 'Date') return isNaN(val.getTime()) ? '' + val : val.toISOString(val); if (tag === 'Error' || val instanceof Error) return '[' + errorToString.call(val) + ']'; if (tag === 'RegExp') return regExpToString.call(val); return null; } function printValue(value, quoteStrings) { let result = printSimpleValue(value, quoteStrings); if (result !== null) return result; return JSON.stringify(value, function (key, value) { let result = printSimpleValue(this[key], quoteStrings); if (result !== null) return result; return value; }, 2); } function toArray(value) { return value == null ? [] : [].concat(value); } let _Symbol$toStringTag; let strReg = /\$\{\s*(\w+)\s*\}/g; _Symbol$toStringTag = Symbol.toStringTag; class ValidationError extends Error { static formatError(message, params) { const path = params.label || params.path || 'this'; if (path !== params.path) params = Object.assign({}, params, { path }); if (typeof message === 'string') return message.replace(strReg, (_, key) => printValue(params[key])); if (typeof message === 'function') return message(params); return message; } static isError(err) { return err && err.name === 'ValidationError'; } constructor(errorOrErrors, value, field, type, disableStack) { super(); this.value = void 0; this.path = void 0; this.type = void 0; this.errors = void 0; this.params = void 0; this.inner = void 0; this[_Symbol$toStringTag] = 'Error'; this.name = 'ValidationError'; this.value = value; this.path = field; this.type = type; this.errors = []; this.inner = []; toArray(errorOrErrors).forEach(err => { if (ValidationError.isError(err)) { this.errors.push(...err.errors); const innerErrors = err.inner.length ? err.inner : [err]; this.inner.push(...innerErrors); } else { this.errors.push(err); } }); this.message = this.errors.length > 1 ? `${this.errors.length} errors occurred` : this.errors[0]; if (!disableStack && Error.captureStackTrace) Error.captureStackTrace(this, ValidationError); } } let mixed = { default: '${path} is invalid', required: '${path} is a required field', defined: '${path} must be defined', notNull: '${path} cannot be null', oneOf: '${path} must be one of the following values: ${values}', notOneOf: '${path} must not be one of the following values: ${values}', notType: ({ path, type, value, originalValue }) => { const castMsg = originalValue != null && originalValue !== value ? ` (cast from the value \`${printValue(originalValue, true)}\`).` : '.'; return type !== 'mixed' ? `${path} must be a \`${type}\` type, ` + `but the final value was: \`${printValue(value, true)}\`` + castMsg : `${path} must match the configured type. ` + `The validated value was: \`${printValue(value, true)}\`` + castMsg; } }; let string = { length: '${path} must be exactly ${length} characters', min: '${path} must be at least ${min} characters', max: '${path} must be at most ${max} characters', matches: '${path} must match the following: "${regex}"', email: '${path} must be a valid email', url: '${path} must be a valid URL', uuid: '${path} must be a valid UUID', trim: '${path} must be a trimmed string', lowercase: '${path} must be a lowercase string', uppercase: '${path} must be a upper case string' }; let number = { min: '${path} must be greater than or equal to ${min}', max: '${path} must be less than or equal to ${max}', lessThan: '${path} must be less than ${less}', moreThan: '${path} must be greater than ${more}', positive: '${path} must be a positive number', negative: '${path} must be a negative number', integer: '${path} must be an integer' }; let date = { min: '${path} field must be later than ${min}', max: '${path} field must be at earlier than ${max}' }; let boolean = { isValue: '${path} field must be ${value}' }; let object = { noUnknown: '${path} field has unspecified keys: ${unknown}' }; let array = { min: '${path} field must have at least ${min} items', max: '${path} field must have less than or equal to ${max} items', length: '${path} must have ${length} items' }; let tuple = { notType: params => { const { path, value, spec } = params; const typeLen = spec.types.length; if (Array.isArray(value)) { if (value.length < typeLen) return `${path} tuple value has too few items, expected a length of ${typeLen} but got ${value.length} for value: \`${printValue(value, true)}\``; if (value.length > typeLen) return `${path} tuple value has too many items, expected a length of ${typeLen} but got ${value.length} for value: \`${printValue(value, true)}\``; } return ValidationError.formatError(mixed.notType, params); } }; var locale = Object.assign(Object.create(null), { mixed, string, number, date, object, array, boolean, tuple }); const isSchema = obj => obj && obj.__isYupSchema__; class Condition { static fromOptions(refs, config) { if (!config.then && !config.otherwise) throw new TypeError('either `then:` or `otherwise:` is required for `when()` conditions'); let { is, then, otherwise } = config; let check = typeof is === 'function' ? is : (...values) => values.every(value => value === is); return new Condition(refs, (values, schema) => { var _branch; let branch = check(...values) ? then : otherwise; return (_branch = branch == null ? void 0 : branch(schema)) != null ? _branch : schema; }); } constructor(refs, builder) { this.fn = void 0; this.refs = refs; this.refs = refs; this.fn = builder; } resolve(base, options) { let values = this.refs.map(ref => // TODO: ? operator here? ref.getValue(options == null ? void 0 : options.value, options == null ? void 0 : options.parent, options == null ? void 0 : options.context)); let schema = this.fn(values, base, options); if (schema === undefined || // @ts-ignore this can be base schema === base) { return base; } if (!isSchema(schema)) throw new TypeError('conditions must return a schema object'); return schema.resolve(options); } } const prefixes = { context: '$', value: '.' }; function create$9(key, options) { return new Reference(key, options); } class Reference { constructor(key, options = {}) { this.key = void 0; this.isContext = void 0; this.isValue = void 0; this.isSibling = void 0; this.path = void 0; this.getter = void 0; this.map = void 0; if (typeof key !== 'string') throw new TypeError('ref must be a string, got: ' + key); this.key = key.trim(); if (key === '') throw new TypeError('ref must be a non-empty string'); this.isContext = this.key[0] === prefixes.context; this.isValue = this.key[0] === prefixes.value; this.isSibling = !this.isContext && !this.isValue; let prefix = this.isContext ? prefixes.context : this.isValue ? prefixes.value : ''; this.path = this.key.slice(prefix.length); this.getter = this.path && propertyExpr.getter(this.path, true); this.map = options.map; } getValue(value, parent, context) { let result = this.isContext ? context : this.isValue ? value : parent; if (this.getter) result = this.getter(result || {}); if (this.map) result = this.map(result); return result; } /** * * @param {*} value * @param {Object} options * @param {Object=} options.context * @param {Object=} options.parent */ cast(value, options) { return this.getValue(value, options == null ? void 0 : options.parent, options == null ? void 0 : options.context); } resolve() { return this; } describe() { return { type: 'ref', key: this.key }; } toString() { return `Ref(${this.key})`; } static isRef(value) { return value && value.__isYupRef; } } // @ts-ignore Reference.prototype.__isYupRef = true; const isAbsent = value => value == null; function createValidation(config) { function validate({ value, path = '', options, originalValue, schema }, panic, next) { const { name, test, params, message, skipAbsent } = config; let { parent, context, abortEarly = schema.spec.abortEarly, disableStackTrace = schema.spec.disableStackTrace } = options; function resolve(item) { return Reference.isRef(item) ? item.getValue(value, parent, context) : item; } function createError(overrides = {}) { var _overrides$disableSta; const nextParams = Object.assign({ value, originalValue, label: schema.spec.label, path: overrides.path || path, spec: schema.spec }, params, overrides.params); for (const key of Object.keys(nextParams)) nextParams[key] = resolve(nextParams[key]); const error = new ValidationError(ValidationError.formatError(overrides.message || message, nextParams), value, nextParams.path, overrides.type || name, (_overrides$disableSta = overrides.disableStackTrace) != null ? _overrides$disableSta : disableStackTrace); error.params = nextParams; return error; } const invalid = abortEarly ? panic : next; let ctx = { path, parent, type: name, from: options.from, createError, resolve, options, originalValue, schema }; const handleResult = validOrError => { if (ValidationError.isError(validOrError)) invalid(validOrError);else if (!validOrError) invalid(createError());else next(null); }; const handleError = err => { if (ValidationError.isError(err)) invalid(err);else panic(err); }; const shouldSkip = skipAbsent && isAbsent(value); if (shouldSkip) { return handleResult(true); } let result; try { var _result; result = test.call(ctx, value, ctx); if (typeof ((_result = result) == null ? void 0 : _result.then) === 'function') { if (options.sync) { throw new Error(`Validation test of type: "${ctx.type}" returned a Promise during a synchronous validate. ` + `This test will finish after the validate call has returned`); } return Promise.resolve(result).then(handleResult, handleError); } } catch (err) { handleError(err); return; } handleResult(result); } validate.OPTIONS = config; return validate; } function getIn(schema, path, value, context = value) { let parent, lastPart, lastPartDebug; // root path: '' if (!path) return { parent, parentPath: path, schema }; propertyExpr.forEach(path, (_part, isBracket, isArray) => { let part = isBracket ? _part.slice(1, _part.length - 1) : _part; schema = schema.resolve({ context, parent, value }); let isTuple = schema.type === 'tuple'; let idx = isArray ? parseInt(part, 10) : 0; if (schema.innerType || isTuple) { if (isTuple && !isArray) throw new Error(`Yup.reach cannot implicitly index into a tuple type. the path part "${lastPartDebug}" must contain an index to the tuple element, e.g. "${lastPartDebug}[0]"`); if (value && idx >= value.length) { throw new Error(`Yup.reach cannot resolve an array item at index: ${_part}, in the path: ${path}. ` + `because there is no value at that index. `); } parent = value; value = value && value[idx]; schema = isTuple ? schema.spec.types[idx] : schema.innerType; } // sometimes the array index part of a path doesn't exist: "nested.arr.child" // in these cases the current part is the next schema and should be processed // in this iteration. For cases where the index signature is included this // check will fail and we'll handle the `child` part on the next iteration like normal if (!isArray) { if (!schema.fields || !schema.fields[part]) throw new Error(`The schema does not contain the path: ${path}. ` + `(failed at: ${lastPartDebug} which is a type: "${schema.type}")`); parent = value; value = value && value[part]; schema = schema.fields[part]; } lastPart = part; lastPartDebug = isBracket ? '[' + _part + ']' : '.' + _part; }); return { schema, parent, parentPath: lastPart }; } function reach(obj, path, value, context) { return getIn(obj, path, value, context).schema; } class ReferenceSet extends Set { describe() { const description = []; for (const item of this.values()) { description.push(Reference.isRef(item) ? item.describe() : item); } return description; } resolveAll(resolve) { let result = []; for (const item of this.values()) { result.push(resolve(item)); } return result; } clone() { return new ReferenceSet(this.values()); } merge(newItems, removeItems) { const next = this.clone(); newItems.forEach(value => next.add(value)); removeItems.forEach(value => next.delete(value)); return next; } } // tweaked from https://github.com/Kelin2025/nanoclone/blob/0abeb7635bda9b68ef2277093f76dbe3bf3948e1/src/index.js function clone(src, seen = new Map()) { if (isSchema(src) || !src || typeof src !== 'object') return src; if (seen.has(src)) return seen.get(src); let copy; if (src instanceof Date) { // Date copy = new Date(src.getTime()); seen.set(src, copy); } else if (src instanceof RegExp) { // RegExp copy = new RegExp(src); seen.set(src, copy); } else if (Array.isArray(src)) { // Array copy = new Array(src.length); seen.set(src, copy); for (let i = 0; i < src.length; i++) copy[i] = clone(src[i], seen); } else if (src instanceof Map) { // Map copy = new Map(); seen.set(src, copy); for (const [k, v] of src.entries()) copy.set(k, clone(v, seen)); } else if (src instanceof Set) { // Set copy = new Set(); seen.set(src, copy); for (const v of src) copy.add(clone(v, seen)); } else if (src instanceof Object) { // Object copy = {}; seen.set(src, copy); for (const [k, v] of Object.entries(src)) copy[k] = clone(v, seen); } else { throw Error(`Unable to clone ${src}`); } return copy; } // If `CustomSchemaMeta` isn't extended with any keys, we'll fall back to a // loose Record definition allowing free form usage. class Schema { constructor(options) { this.type = void 0; this.deps = []; this.tests = void 0; this.transforms = void 0; this.conditions = []; this._mutate = void 0; this.internalTests = {}; this._whitelist = new ReferenceSet(); this._blacklist = new ReferenceSet(); this.exclusiveTests = Object.create(null); this._typeCheck = void 0; this.spec = void 0; this.tests = []; this.transforms = []; this.withMutation(() => { this.typeError(mixed.notType); }); this.type = options.type; this._typeCheck = options.check; this.spec = Object.assign({ strip: false, strict: false, abortEarly: true, recursive: true, disableStackTrace: false, nullable: false, optional: true, coerce: true }, options == null ? void 0 : options.spec); this.withMutation(s => { s.nonNullable(); }); } // TODO: remove get _type() { return this.type; } clone(spec) { if (this._mutate) { if (spec) Object.assign(this.spec, spec); return this; } // if the nested value is a schema we can skip cloning, since // they are already immutable const next = Object.create(Object.getPrototypeOf(this)); // @ts-expect-error this is readonly next.type = this.type; next._typeCheck = this._typeCheck; next._whitelist = this._whitelist.clone(); next._blacklist = this._blacklist.clone(); next.internalTests = Object.assign({}, this.internalTests); next.exclusiveTests = Object.assign({}, this.exclusiveTests); // @ts-expect-error this is readonly next.deps = [...this.deps]; next.conditions = [...this.conditions]; next.tests = [...this.tests]; next.transforms = [...this.transforms]; next.spec = clone(Object.assign({}, this.spec, spec)); return next; } label(label) { let next = this.clone(); next.spec.label = label; return next; } meta(...args) { if (args.length === 0) return this.spec.meta; let next = this.clone(); next.spec.meta = Object.assign(next.spec.meta || {}, args[0]); return next; } withMutation(fn) { let before = this._mutate; this._mutate = true; let result = fn(this); this._mutate = before; return result; } concat(schema) { if (!schema || schema === this) return this; if (schema.type !== this.type && this.type !== 'mixed') throw new TypeError(`You cannot \`concat()\` schema's of different types: ${this.type} and ${schema.type}`); let base = this; let combined = schema.clone(); const mergedSpec = Object.assign({}, base.spec, combined.spec); combined.spec = mergedSpec; combined.internalTests = Object.assign({}, base.internalTests, combined.internalTests); // manually merge the blacklist/whitelist (the other `schema` takes // precedence in case of conflicts) combined._whitelist = base._whitelist.merge(schema._whitelist, schema._blacklist); combined._blacklist = base._blacklist.merge(schema._blacklist, schema._whitelist); // start with the current tests combined.tests = base.tests; combined.exclusiveTests = base.exclusiveTests; // manually add the new tests to ensure // the deduping logic is consistent combined.withMutation(next => { schema.tests.forEach(fn => { next.test(fn.OPTIONS); }); }); combined.transforms = [...base.transforms, ...combined.transforms]; return combined; } isType(v) { if (v == null) { if (this.spec.nullable && v === null) return true; if (this.spec.optional && v === undefined) return true; return false; } return this._typeCheck(v); } resolve(options) { let schema = this; if (schema.conditions.length) { let conditions = schema.conditions; schema = schema.clone(); schema.conditions = []; schema = conditions.reduce((prevSchema, condition) => condition.resolve(prevSchema, options), schema); schema = schema.resolve(options); } return schema; } resolveOptions(options) { var _options$strict, _options$abortEarly, _options$recursive, _options$disableStack; return Object.assign({}, options, { from: options.from || [], strict: (_options$strict = options.strict) != null ? _options$strict : this.spec.strict, abortEarly: (_options$abortEarly = options.abortEarly) != null ? _options$abortEarly : this.spec.abortEarly, recursive: (_options$recursive = options.recursive) != null ? _options$recursive : this.spec.recursive, disableStackTrace: (_options$disableStack = options.disableStackTrace) != null ? _options$disableStack : this.spec.disableStackTrace }); } /** * Run the configured transform pipeline over an input value. */ cast(value, options = {}) { let resolvedSchema = this.resolve(Object.assign({ value }, options)); let allowOptionality = options.assert === 'ignore-optionality'; let result = resolvedSchema._cast(value, options); if (options.assert !== false && !resolvedSchema.isType(result)) { if (allowOptionality && isAbsent(result)) { return result; } let formattedValue = printValue(value); let formattedResult = printValue(result); throw new TypeError(`The value of ${options.path || 'field'} could not be cast to a value ` + `that satisfies the schema type: "${resolvedSchema.type}". \n\n` + `attempted value: ${formattedValue} \n` + (formattedResult !== formattedValue ? `result of cast: ${formattedResult}` : '')); } return result; } _cast(rawValue, options) { let value = rawValue === undefined ? rawValue : this.transforms.reduce((prevValue, fn) => fn.call(this, prevValue, rawValue, this), rawValue); if (value === undefined) { value = this.getDefault(options); } return value; } _validate(_value, options = {}, panic, next) { let { path, originalValue = _value, strict = this.spec.strict } = options; let value = _value; if (!strict) { value = this._cast(value, Object.assign({ assert: false }, options)); } let initialTests = []; for (let test of Object.values(this.internalTests)) { if (test) initialTests.push(test); } this.runTests({ path, value, originalValue, options, tests: initialTests }, panic, initialErrors => { // even if we aren't ending early we can't proceed further if the types aren't correct if (initialErrors.length) { return next(initialErrors, value); } this.runTests({ path, value, originalValue, options, tests: this.tests }, panic, next); }); } /** * Executes a set of validations, either schema, produced Tests or a nested * schema validate result. */ runTests(runOptions, panic, next) { let fired = false; let { tests, value, originalValue, path, options } = runOptions; let panicOnce = arg => { if (fired) return; fired = true; panic(arg, value); }; let nextOnce = arg => { if (fired) return; fired = true; next(arg, value); }; let count = tests.length; let nestedErrors = []; if (!count) return nextOnce([]); let args = { value, originalValue, path, options, schema: this }; for (let i = 0; i < tests.length; i++) { const test = tests[i]; test(args, panicOnce, function finishTestRun(err) { if (err) { Array.isArray(err) ? nestedErrors.push(...err) : nestedErrors.push(err); } if (--count <= 0) { nextOnce(nestedErrors); } }); } } asNestedTest({ key, index, parent, parentPath, originalParent, options }) { const k = key != null ? key : index; if (k == null) { throw TypeError('Must include `key` or `index` for nested validations'); } const isIndex = typeof k === 'number'; let value = parent[k]; const testOptions = Object.assign({}, options, { // Nested validations fields are always strict: // 1. parent isn't strict so the casting will also have cast inner values // 2. parent is strict in which case the nested values weren't cast either strict: true, parent, value, originalValue: originalParent[k], // FIXME: tests depend on `index` being passed around deeply, // we should not let the options.key/index bleed through key: undefined, // index: undefined, [isIndex ? 'index' : 'key']: k, path: isIndex || k.includes('.') ? `${parentPath || ''}[${value ? k : `"${k}"`}]` : (parentPath ? `${parentPath}.` : '') + key }); return (_, panic, next) => this.resolve(testOptions)._validate(value, testOptions, panic, next); } validate(value, options) { var _options$disableStack2; let schema = this.resolve(Object.assign({}, options, { value })); let disableStackTrace = (_options$disableStack2 = options == null ? void 0 : options.disableStackTrace) != null ? _options$disableStack2 : schema.spec.disableStackTrace; return new Promise((resolve, reject) => schema._validate(value, options, (error, parsed) => { if (ValidationError.isError(error)) error.value = parsed; reject(error); }, (errors, validated) => { if (errors.length) reject(new ValidationError(errors, validated, undefined, undefined, disableStackTrace));else resolve(validated); })); } validateSync(value, options) { var _options$disableStack3; let schema = this.resolve(Object.assign({}, options, { value })); let result; let disableStackTrace = (_options$disableStack3 = options == null ? void 0 : options.disableStackTrace) != null ? _options$disableStack3 : schema.spec.disableStackTrace; schema._validate(value, Object.assign({}, options, { sync: true }), (error, parsed) => { if (ValidationError.isError(error)) error.value = parsed; throw error; }, (errors, validated) => { if (errors.length) throw new ValidationError(errors, value, undefined, undefined, disableStackTrace); result = validated; }); return result; } isValid(value, options) { return this.validate(value, options).then(() => true, err => { if (ValidationError.isError(err)) return false; throw err; }); } isValidSync(value, options) { try { this.validateSync(value, options); return true; } catch (err) { if (ValidationError.isError(err)) return false; throw err; } } _getDefault(options) { let defaultValue = this.spec.default; if (defaultValue == null) { return defaultValue; } return typeof defaultValue === 'function' ? defaultValue.call(this, options) : clone(defaultValue); } getDefault(options // If schema is defaulted we know it's at least not undefined ) { let schema = this.resolve(options || {}); return schema._getDefault(options); } default(def) { if (arguments.length === 0) { return this._getDefault(); } let next = this.clone({ default: def }); return next; } strict(isStrict = true) { return this.clone({ strict: isStrict }); } nullability(nullable, message) { const next = this.clone({ nullable }); next.internalTests.nullable = createValidation({ message, name: 'nullable', test(value) { return value === null ? this.schema.spec.nullable : true; } }); return next; } optionality(optional, message) { const next = this.clone({ optional }); next.internalTests.optionality = createValidation({ message, name: 'optionality', test(value) { return value === undefined ? this.schema.spec.optional : true; } }); return next; } optional() { return this.optionality(true); } defined(message = mixed.defined) { return this.optionality(false, message); } nullable() { return this.nullability(true); } nonNullable(message = mixed.notNull) { return this.nullability(false, message); } required(message = mixed.required) { return this.clone().withMutation(next => next.nonNullable(message).defined(message)); } notRequired() { return this.clone().withMutation(next => next.nullable().optional()); } transform(fn) { let next = this.clone(); next.transforms.push(fn); return next; } /** * Adds a test function to the schema's queue of tests. * tests can be exclusive or non-exclusive. * * - exclusive tests, will replace any existing tests of the same name. * - non-exclusive: can be stacked * * If a non-exclusive test is added to a schema with an exclusive test of the same name * the exclusive test is removed and further tests of the same name will be stacked. * * If an exclusive test is added to a schema with non-exclusive tests of the same name * the previous tests are removed and further tests of the same name will replace each other. */ test(...args) { let opts; if (args.length === 1) { if (typeof args[0] === 'function') { opts = { test: args[0] }; } else { opts = args[0]; } } else if (args.length === 2) { opts = { name: args[0], test: args[1] }; } else { opts = { name: args[0], message: args[1], test: args[2] }; } if (opts.message === undefined) opts.message = mixed.default; if (typeof opts.test !== 'function') throw new TypeError('`test` is a required parameters'); let next = this.clone(); let validate = createValidation(opts); let isExclusive = opts.exclusive || opts.name && next.exclusiveTests[opts.name] === true; if (opts.exclusive) { if (!opts.name) throw new TypeError('Exclusive tests must provide a unique `name` identifying the test'); } if (opts.name) next.exclusiveTests[opts.name] = !!opts.exclusive; next.tests = next.tests.filter(fn => { if (fn.OPTIONS.name === opts.name) { if (isExclusive) return false; if (fn.OPTIONS.test === validate.OPTIONS.test) return false; } return true; }); next.tests.push(validate); return next; } when(keys, options) { if (!Array.isArray(keys) && typeof keys !== 'string') { options = keys; keys = '.'; } let next = this.clone(); let deps = toArray(keys).map(key => new Reference(key)); deps.forEach(dep => { // @ts-ignore readonly array if (dep.isSibling) next.deps.push(dep.key); }); next.conditions.push(typeof options === 'function' ? new Condition(deps, options) : Condition.fromOptions(deps, options)); return next; } typeError(message) { let next = this.clone(); next.internalTests.typeError = createValidation({ message, name: 'typeError', skipAbsent: true, test(value) { if (!this.schema._typeCheck(value)) return this.createError({ params: { type: this.schema.type } }); return true; } }); return next; } oneOf(enums, message = mixed.oneOf) { let next = this.clone(); enums.forEach(val => { next._whitelist.add(val); next._blacklist.delete(val); }); next.internalTests.whiteList = createValidation({ message, name: 'oneOf', skipAbsent: true, test(value) { let valids = this.schema._whitelist; let resolved = valids.resolveAll(this.resolve); return resolved.includes(value) ? true : this.createError({ params: { values: Array.from(valids).join(', '), resolved } }); } }); return next; } notOneOf(enums, message = mixed.notOneOf) { let next = this.clone(); enums.forEach(val => { next._blacklist.add(val); next._whitelist.delete(val); }); next.internalTests.blacklist = createValidation({ message, name: 'notOneOf', test(value) { let invalids = this.schema._blacklist; let resolved = invalids.resolveAll(this.resolve); if (resolved.includes(value)) return this.createError({ params: { values: Array.from(invalids).join(', '), resolved } }); return true; } }); return next; } strip(strip = true) { let next = this.clone(); next.spec.strip = strip; return next; } /** * Return a serialized description of the schema including validations, flags, types etc. * * @param options Provide any needed context for resolving runtime schema alterations (lazy, when conditions, etc). */ describe(options) { const next = (options ? this.resolve(options) : this).clone(); const { label, meta, optional, nullable } = next.spec; const description = { meta, label, optional, nullable, default: next.getDefault(options), type: next.type, oneOf: next._whitelist.describe(), notOneOf: next._blacklist.describe(), tests: next.tests.map(fn => ({ name: fn.OPTIONS.name, params: fn.OPTIONS.params })).filter((n, idx, list) => list.findIndex(c => c.name === n.name) === idx) }; return description; } } // @ts-expect-error Schema.prototype.__isYupSchema__ = true; for (const method of ['validate', 'validateSync']) Schema.prototype[`${method}At`] = function (path, value, options = {}) { const { parent, parentPath, schema } = getIn(this, path, value, options.context); return schema[method](parent && parent[parentPath], Object.assign({}, options, { parent, path })); }; for (const alias of ['equals', 'is']) Schema.prototype[alias] = Schema.prototype.oneOf; for (const alias of ['not', 'nope']) Schema.prototype[alias] = Schema.prototype.notOneOf; const returnsTrue = () => true; function create$8(spec) { return new MixedSchema(spec); } class MixedSchema extends Schema { constructor(spec) { super(typeof spec === 'function' ? { type: 'mixed', check: spec } : Object.assign({ type: 'mixed', check: returnsTrue }, spec)); } } create$8.prototype = MixedSchema.prototype; function create$7() { return new BooleanSchema(); } class BooleanSchema extends Schema { constructor() { super({ type: 'boolean', check(v) { if (v instanceof Boolean) v = v.valueOf(); return typeof v === 'boolean'; } }); this.withMutation(() => { this.transform((value, _raw, ctx) => { if (ctx.spec.coerce && !ctx.isType(value)) { if (/^(true|1)$/i.test(String(value))) return true; if (/^(false|0)$/i.test(String(value))) return false; } return value; }); }); } isTrue(message = boolean.isValue) { return this.test({ message, name: 'is-value', exclusive: true, params: { value: 'true' }, test(value) { return isAbsent(value) || value === true; } }); } isFalse(message = boolean.isValue) { return this.test({ message, name: 'is-value', exclusive: true, params: { value: 'false' }, test(value) { return isAbsent(value) || value === false; } }); } default(def) { return super.default(def); } defined(msg) { return super.defined(msg); } optional() { return super.optional(); } required(msg) { return super.required(msg); } notRequired() { return super.notRequired(); } nullable() { return super.nullable(); } nonNullable(msg) { return super.nonNullable(msg); } strip(v) { return super.strip(v); } } create$7.prototype = BooleanSchema.prototype; // Taken from HTML spec: https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address let rEmail = // eslint-disable-next-line /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; let rUrl = // eslint-disable-next-line /^((https?|ftp):)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i; // eslint-disable-next-line let rUUID = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; let isTrimmed = value => isAbsent(value) || value === value.trim(); let objStringTag = {}.toString(); function create$6() { return new StringSchema(); } class StringSchema extends Schema { constructor() { super({ type: 'string', check(value) { if (value instanceof String) value = value.valueOf(); return typeof value === 'string'; } }); this.withMutation(() => { this.transform((value, _raw, ctx) => { if (!ctx.spec.coerce || ctx.isType(value)) return value; // don't ever convert arrays if (Array.isArray(value)) return value; const strValue = value != null && value.toString ? value.toString() : value; // no one wants plain objects converted to [Object object] if (strValue === objStringTag) return value; return strValue; }); }); } required(message) { return super.required(message).withMutation(schema => schema.test({ message: message || mixed.required, name: 'required', skipAbsent: true, test: value => !!value.length })); } notRequired() { return super.notRequired().withMutation(schema => { schema.tests = schema.tests.filter(t => t.OPTIONS.name !== 'required'); return schema; }); } length(length, message = string.length) { return this.test({ message, name: 'length', exclusive: true, params: { length }, skipAbsent: true, test(value) { return value.length === this.resolve(length); } }); } min(min, message = string.min) { return this.test({ message, name: 'min', exclusive: true, params: { min }, skipAbsent: true, test(value) { return value.length >= this.resolve(min); } }); } max(max, message = string.max) { return this.test({ name: 'max', exclusive: true, message, params: { max }, skipAbsent: true, test(value) { return value.length <= this.resolve(max); } }); } matches(regex, options) { let excludeEmptyString = false; let message; let name; if (options) { if (typeof options === 'object') { ({ excludeEmptyString = false, message, name } = options); } else { message = options; } } return this.test({ name: name || 'matches', message: message || string.matches, params: { regex }, skipAbsent: true, test: value => value === '' && excludeEmptyString || value.search(regex) !== -1 }); } email(message = string.email) { return this.matches(rEmail, { name: 'email', message, excludeEmptyString: true }); } url(message = string.url) { return this.matches(rUrl, { name: 'url', message, excludeEmptyString: true }); } uuid(message = string.uuid) { return this.matches(rUUID, { name: 'uuid', message, excludeEmptyString: false }); } //-- transforms -- ensure() { return this.default('').transform(val => val === null ? '' : val); } trim(message = string.trim) { return this.transform(val => val != null ? val.trim() : val).test({ message, name: 'trim', test: isTrimmed }); } lowercase(message = string.lowercase) { return this.transform(value => !isAbsent(value) ? value.toLowerCase() : value).test({ message, name: 'string_case', exclusive: true, skipAbsent: true, test: value => isAbsent(value) || value === value.toLowerCase() }); } uppercase(message = string.uppercase) { return this.transform(value => !isAbsent(value) ? value.toUpperCase() : value).test({ message, name: 'string_case', exclusive: true, skipAbsent: true, test: value => isAbsent(value) || value === value.toUpperCase() }); } } create$6.prototype = StringSchema.prototype; // // String Interfaces // let isNaN$1 = value => value != +value; function create$5() { return new NumberSchema(); } class NumberSchema extends Schema { constructor() { super({ type: 'number', check(value) { if (value instanceof Number) value = value.valueOf(); return typeof value === 'number' && !isNaN$1(value); } }); this.withMutation(() => { this.transform((value, _raw, ctx) => { if (!ctx.spec.coerce) return value; let parsed = value; if (typeof parsed === 'string') { parsed = parsed.replace(/\s/g, ''); if (parsed === '') return NaN; // don't use parseFloat to avoid positives on alpha-numeric strings parsed = +parsed; } // null -> NaN isn't useful; treat all nulls as null and let it fail on // nullability check vs TypeErrors if (ctx.isType(parsed) || parsed === null) return parsed; return parseFloat(parsed); }); }); } min(min, message = number.min) { return this.test({ message, name: 'min', exclusive: true, params: { min }, skipAbsent: true, test(value) { return value >= this.resolve(min); } }); } max(max, message = number.max) { return this.test({ message, name: 'max', exclusive: true, params: { max }, skipAbsent: true, test(value) { return value <= this.resolve(max); } }); } lessThan(less, message = number.lessThan) { return this.test({ message, name: 'max', exclusive: true, params: { less }, skipAbsent: true, test(value) { return value < this.resolve(less); } }); } moreThan(more, message = number.moreThan) { return this.test({ message, name: 'min', exclusive: true, params: { more }, skipAbsent: true, test(value) { return value > this.resolve(more); } }); } positive(msg = number.positive) { return this.moreThan(0, msg); } negative(msg = number.negative) { return this.lessThan(0, msg); } integer(message = number.integer) { return this.test({ name: 'integer', message, skipAbsent: true, test: val => Number.isInteger(val) }); } truncate() { return this.transform(value => !isAbsent(value) ? value | 0 : value); } round(method) { var _method; let avail = ['ceil', 'floor', 'round', 'trunc']; method = ((_method = method) == null ? void 0 : _method.toLowerCase()) || 'round'; // this exists for symemtry with the new Math.trunc if (method === 'trunc') return this.truncate(); if (avail.indexOf(method.toLowerCase()) === -1) throw new TypeError('Only valid options for round() are: ' + avail.join(', ')); return this.transform(value => !isAbsent(value) ? Math[method](value) : value); } } create$5.prototype = NumberSchema.prototype; // // Number Interfaces // /** * This file is a modified version of the file from the following repository: * Date.parse with progressive enhancement for ISO 8601 * NON-CONFORMANT EDITION. * © 2011 Colin Snover * Released under MIT license. */ // prettier-ignore // 1 YYYY 2 MM 3 DD 4 HH 5 mm 6 ss 7 msec 8 Z 9 ± 10 tzHH 11 tzmm const isoReg = /^(\d{4}|[+-]\d{6})(?:-?(\d{2})(?:-?(\d{2}))?)?(?:[ T]?(\d{2}):?(\d{2})(?::?(\d{2})(?:[,.](\d{1,}))?)?(?:(Z)|([+-])(\d{2})(?::?(\d{2}))?)?)?$/; function toNumber(str, defaultValue = 0) { return Number(str) || defaultValue; } function parseIsoDate(date) { const regexResult = isoReg.exec(date); if (!regexResult) return Date.parse ? Date.parse(date) : Number.NaN; // use of toNumber() avoids NaN timestamps caused by “undefined” // values being passed to Date constructor const struct = { year: toNumber(regexResult[1]), month: toNumber(regexResult[2], 1) - 1, day: toNumber(regexResult[3], 1), hour: toNumber(regexResult[4]), minute: toNumber(regexResult[5]), second: toNumber(regexResult[6]), millisecond: regexResult[7] ? // allow arbitrary sub-second precision beyond milliseconds toNumber(regexResult[7].substring(0, 3)) : 0, z: regexResult[8] || undefined, plusMinus: regexResult[9] || undefined, hourOffset: toNumber(regexResult[10]), minuteOffset: toNumber(regexResult[11]) }; // timestamps without timezone identifiers should be considered local time if (struct.z === undefined && struct.plusMinus === undefined) { return new Date(struct.year, struct.month, struct.day, struct.hour, struct.minute, struct.second, struct.millisecond).valueOf(); } let totalMinutesOffset = 0; if (struct.z !== 'Z' && struct.plusMinus !== undefined) { totalMinutesOffset = struct.hourOffset * 60 + struct.minuteOffset; if (struct.plusMinus === '+') totalMinutesOffset = 0 - totalMinutesOffset; } return Date.UTC(struct.year, struct.month, struct.day, struct.hour, struct.minute + totalMinutesOffset, struct.second, struct.millisecond); } let invalidDate = new Date(''); let isDate = obj => Object.prototype.toString.call(obj) === '[object Date]'; function create$4() { return new DateSchema(); } class DateSchema extends Schema { constructor() { super({ type: 'date', check(v) { return isDate(v) && !isNaN(v.getTime()); } }); this.withMutation(() => { this.transform((value, _raw, ctx) => { // null -> InvalidDate isn't useful; treat all nulls as null and let it fail on // nullability check vs TypeErrors if (!ctx.spec.coerce || ctx.isType(value) || value === null) return value; value = parseIsoDate(value); // 0 is a valid timestamp equivalent to 1970-01-01T00:00:00Z(unix epoch) or before. return !isNaN(value) ? new Date(value) : DateSchema.INVALID_DATE; }); }); } prepareParam(ref, name) { let param; if (!Reference.isRef(ref)) { let cast = this.cast(ref); if (!this._typeCheck(cast)) throw new TypeError(`\`${name}\` must be a Date or a value that can be \`cast()\` to a Date`); param = cast; } else { param = ref; } return param; } min(min, message = date.min) { let limit = this.prepareParam(min, 'min'); return this.test({ message, name: 'min', exclusive: true, params: { min }, skipAbsent: true, test(value) { return value >= this.resolve(limit); } }); } max(max, message = date.max) { let limit = this.prepareParam(max, 'max'); return this.test({ message, name: 'max', exclusive: true, params: { max }, skipAbsent: true, test(value) { return value <= this.resolve(limit); } }); } } DateSchema.INVALID_DATE = invalidDate; create$4.prototype = DateSchema.prototype; create$4.INVALID_DATE = invalidDate; // @ts-expect-error function sortFields(fields, excludedEdges = []) { let edges = []; let nodes = new Set(); let excludes = new Set(excludedEdges.map(([a, b]) => `${a}-${b}`)); function addNode(depPath, key) { let node = propertyExpr.split(depPath)[0]; nodes.add(node); if (!excludes.has(`${key}-${node}`)) edges.push([key, node]); } for (const key of Object.keys(fields)) { let value = fields[key]; nodes.add(key); if (Reference.isRef(value) && value.isSibling) addNode(value.path, key);else if (isSchema(value) && 'deps' in value) value.deps.forEach(path => addNode(path, key)); } return toposort__default["default"].array(Array.from(nodes), edges).reverse(); } function findIndex(arr, err) { let idx = Infinity; arr.some((key, ii) => { var _err$path; if ((_err$path = err.path) != null && _err$path.includes(key)) { idx = ii; return true; } }); return idx; } function sortByKeyOrder(keys) { return (a, b) => { return findIndex(keys, a) - findIndex(keys, b); }; } const parseJson = (value, _, ctx) => { if (typeof value !== 'string') { return value; } let parsed = value; try { parsed = JSON.parse(value); } catch (err) { /* */ } return ctx.isType(parsed) ? parsed : value; }; // @ts-ignore function deepPartial(schema) { if ('fields' in schema) { const partial = {}; for (const [key, fieldSchema] of Object.entries(schema.fields)) { partial[key] = deepPartial(fieldSchema); } return schema.setFields(partial); } if (schema.type === 'array') { const nextArray = schema.optional(); if (nextArray.innerType) nextArray.innerType = deepPartial(nextArray.innerType); return nextArray; } if (schema.type === 'tuple') { return schema.optional().clone({ types: schema.spec.types.map(deepPartial) }); } if ('optional' in schema) { return schema.optional(); } return schema; } const deepHas = (obj, p) => { const path = [...propertyExpr.normalizePath(p)]; if (path.length === 1) return path[0] in obj; let last = path.pop(); let parent = propertyExpr.getter(propertyExpr.join(path), true)(obj); return !!(parent && last in parent); }; let isObject = obj => Object.prototype.toString.call(obj) === '[object Object]'; function unknown(ctx, value) { let known = Object.keys(ctx.fields); return Object.keys(value).filter(key => known.indexOf(key) === -1); } const defaultSort = sortByKeyOrder([]); function create$3(spec) { return new ObjectSchema(spec); } class ObjectSchema extends Schema { constructor(spec) { super({ type: 'object', check(value) { return isObject(value) || typeof value === 'function'; } }); this.fields = Object.create(null); this._sortErrors = defaultSort; this._nodes = []; this._excludedEdges = []; this.withMutation(() => { if (spec) { this.shape(spec); } }); } _cast(_value, options = {}) { var _options$stripUnknown; let value = super._cast(_value, options); //should ignore nulls here if (value === undefined) return this.getDefault(options); if (!this._typeCheck(value)) return value; let fields = this.fields; let strip = (_options$stripUnknown = options.stripUnknown) != null ? _options$stripUnknown : this.spec.noUnknown; let props = [].concat(this._nodes, Object.keys(value).filter(v => !this._nodes.includes(v))); let intermediateValue = {}; // is filled during the transform below let innerOptions = Object.assign({}, options, { parent: intermediateValue, __validating: options.__validating || false }); let isChanged = false; for (const prop of props) { let field = fields[prop]; let exists = (prop in value); if (field) { let fieldValue; let inputValue = value[prop]; // safe to mutate since this is fired in sequence innerOptions.path = (options.path ? `${options.path}.` : '') + prop; field = field.resolve({ value: inputValue, context: options.context, parent: intermediateValue }); let fieldSpec = field instanceof Schema ? field.spec : undefined; let strict = fieldSpec == null ? void 0 : fieldSpec.strict; if (fieldSpec != null && fieldSpec.strip) { isChanged = isChanged || prop in value; continue; } fieldValue = !options.__validating || !strict ? // TODO: use _cast, this is double resolving field.cast(value[prop], innerOptions) : value[prop]; if (fieldValue !== undefined) { intermediateValue[prop] = fieldValue; } } else if (exists && !strip) { intermediateValue[prop] = value[prop]; } if (exists !== prop in intermediateValue || intermediateValue[prop] !== value[prop]) { isChanged = true; } } return isChanged ? intermediateValue : value; } _validate(_value, options = {}, panic, next) { let { from = [], originalValue = _value, recursive = this.spec.recursive } = options; options.from = [{ schema: this, value: originalValue }, ...from]; // this flag is needed for handling `strict` correctly in the context of // validation vs just casting. e.g strict() on a field is only used when validating options.__validating = true; options.originalValue = originalValue; super._validate(_value, options, panic, (objectErrors, value) => { if (!recursive || !isObject(value)) { next(objectErrors, value); return; } originalValue = originalValue || value; let tests = []; for (let key of this._nodes) { let field = this.fields[key]; if (!field || Reference.isRef(field)) { continue; } tests.push(field.asNestedTest({ options, key, parent: value, parentPath: options.path, originalParent: originalValue })); } this.runTests({ tests, value, originalValue, options }, panic, fieldErrors => { next(fieldErrors.sort(this._sortErrors).concat(objectErrors), value); }); }); } clone(spec) { const next = super.clone(spec); next.fields = Object.assign({}, this.fields); next._nodes = this._nodes; next._excludedEdges = this._excludedEdges; next._sortErrors = this._sortErrors; return next; } concat(schema) { let next = super.concat(schema); let nextFields = next.fields; for (let [field, schemaOrRef] of Object.entries(this.fields)) { const target = nextFields[field]; nextFields[field] = target === undefined ? schemaOrRef : target; } return next.withMutation(s => // XXX: excludes here is wrong s.setFields(nextFields, [...this._excludedEdges, ...schema._excludedEdges])); } _getDefault(options) { if ('default' in this.spec) { return super._getDefault(options); } // if there is no default set invent one if (!this._nodes.length) { return undefined; } let dft = {}; this._nodes.forEach(key => { var _innerOptions; const field = this.fields[key]; let innerOptions = options; if ((_innerOptions = innerOptions) != null && _innerOptions.value) { innerOptions = Object.assign({}, innerOptions, { parent: innerOptions.value, value: innerOptions.value[key] }); } dft[key] = field && 'getDefault' in field ? field.getDefault(innerOptions) : undefined; }); return dft; } setFields(shape, excludedEdges) { let next = this.clone(); next.fields = shape; next._nodes = sortFields(shape, excludedEdges); next._sortErrors = sortByKeyOrder(Object.keys(shape)); // XXX: this carries over edges which may not be what you want if (excludedEdges) next._excludedEdges = excludedEdges; return next; } shape(additions, excludes = []) { return this.clone().withMutation(next => { let edges = next._excludedEdges; if (excludes.length) { if (!Array.isArray(excludes[0])) excludes = [excludes]; edges = [...next._excludedEdges, ...excludes]; } // XXX: excludes here is wrong return next.setFields(Object.assign(next.fields, additions), edges); }); } partial() { const partial = {}; for (const [key, schema] of Object.entries(this.fields)) { partial[key] = 'optional' in schema && schema.optional instanceof Function ? schema.optional() : schema; } return this.setFields(partial); } deepPartial() { const next = deepPartial(this); return next; } pick(keys) { const picked = {}; for (const key of keys) { if (this.fields[key]) picked[key] = this.fields[key]; } return this.setFields(picked, this._excludedEdges.filter(([a, b]) => keys.includes(a) && keys.includes(b))); } omit(keys) { const remaining = []; for (const key of Object.keys(this.fields)) { if (keys.includes(key)) continue; remaining.push(key); } return this.pick(remaining); } from(from, to, alias) { let fromGetter = propertyExpr.getter(from, true); return this.transform(obj => { if (!obj) return obj; let newObj = obj; if (deepHas(obj, from)) { newObj = Object.assign({}, obj); if (!alias) delete newObj[from]; newObj[to] = fromGetter(obj); } return newObj; }); } /** Parse an input JSON string to an object */ json() { return this.transform(parseJson); } noUnknown(noAllow = true, message = object.noUnknown) { if (typeof noAllow !== 'boolean') { message = noAllow; noAllow = true; } let next = this.test({ name: 'noUnknown', exclusive: true, message: message, test(value) { if (value == null) return true; const unknownKeys = unknown(this.schema, value); return !noAllow || unknownKeys.length === 0 || this.createError({ params: { unknown: unknownKeys.join(', ') } }); } }); next.spec.noUnknown = noAllow; return next; } unknown(allow = true, message = object.noUnknown) { return this.noUnknown(!allow, message); } transformKeys(fn) { return this.transform(obj => { if (!obj) return obj; const result = {}; for (const key of Object.keys(obj)) result[fn(key)] = obj[key]; return result; }); } camelCase() { return this.transformKeys(tinyCase.camelCase); } snakeCase() { return this.transformKeys(tinyCase.snakeCase); } constantCase() { return this.transformKeys(key => tinyCase.snakeCase(key).toUpperCase()); } describe(options) { const next = (options ? this.resolve(options) : this).clone(); const base = super.describe(options); base.fields = {}; for (const [key, value] of Object.entries(next.fields)) { var _innerOptions2; let innerOptions = options; if ((_innerOptions2 = innerOptions) != null && _innerOptions2.value) { innerOptions = Object.assign({}, innerOptions, { parent: innerOptions.value, value: innerOptions.value[key] }); } base.fields[key] = value.describe(innerOptions); } return base; } } create$3.prototype = ObjectSchema.prototype; function create$2(type) { return new ArraySchema(type); } class ArraySchema extends Schema { constructor(type) { super({ type: 'array', spec: { types: type }, check(v) { return Array.isArray(v); } }); // `undefined` specifically means uninitialized, as opposed to "no subtype" this.innerType = void 0; this.innerType = type; } _cast(_value, _opts) { const value = super._cast(_value, _opts); // should ignore nulls here if (!this._typeCheck(value) || !this.innerType) { return value; } let isChanged = false; const castArray = value.map((v, idx) => { const castElement = this.innerType.cast(v, Object.assign({}, _opts, { path: `${_opts.path || ''}[${idx}]` })); if (castElement !== v) { isChanged = true; } return castElement; }); return isChanged ? castArray : value; } _validate(_value, options = {}, panic, next) { var _options$recursive; // let sync = options.sync; // let path = options.path; let innerType = this.innerType; // let endEarly = options.abortEarly ?? this.spec.abortEarly; let recursive = (_options$recursive = options.recursive) != null ? _options$recursive : this.spec.recursive; options.originalValue != null ? options.originalValue : _value; super._validate(_value, options, panic, (arrayErrors, value) => { var _options$originalValu2; if (!recursive || !innerType || !this._typeCheck(value)) { next(arrayErrors, value); return; } // #950 Ensure that sparse array empty slots are validated let tests = new Array(value.length); for (let index = 0; index < value.length; index++) { var _options$originalValu; tests[index] = innerType.asNestedTest({ options, index, parent: value, parentPath: options.path, originalParent: (_options$originalValu = options.originalValue) != null ? _options$originalValu : _value }); } this.runTests({ value, tests, originalValue: (_options$originalValu2 = options.originalValue) != null ? _options$originalValu2 : _value, options }, panic, innerTypeErrors => next(innerTypeErrors.concat(arrayErrors), value)); }); } clone(spec) { const next = super.clone(spec); // @ts-expect-error readonly next.innerType = this.innerType; return next; } /** Parse an input JSON string to an object */ json() { return this.transform(parseJson); } concat(schema) { let next = super.concat(schema); // @ts-expect-error readonly next.innerType = this.innerType; if (schema.innerType) // @ts-expect-error readonly next.innerType = next.innerType ? // @ts-expect-error Lazy doesn't have concat and will break next.innerType.concat(schema.innerType) : schema.innerType; return next; } of(schema) { // FIXME: this should return a new instance of array without the default to be let next = this.clone(); if (!isSchema(schema)) throw new TypeError('`array.of()` sub-schema must be a valid yup schema not: ' + printValue(schema)); // @ts-expect-error readonly next.innerType = schema; next.spec = Object.assign({}, next.spec, { types: schema }); return next; } length(length, message = array.length) { return this.test({ message, name: 'length', exclusive: true, params: { length }, skipAbsent: true, test(value) { return value.length === this.resolve(length); } }); } min(min, message) { message = message || array.min; return this.test({ message, name: 'min', exclusive: true, params: { min }, skipAbsent: true, // FIXME(ts): Array test(value) { return value.length >= this.resolve(min); } }); } max(max, message) { message = message || array.max; return this.test({ message, name: 'max', exclusive: true, params: { max }, skipAbsent: true, test(value) { return value.length <= this.resolve(max); } }); } ensure() { return this.default(() => []).transform((val, original) => { // We don't want to return `null` for nullable schema if (this._typeCheck(val)) return val; return original == null ? [] : [].concat(original); }); } compact(rejector) { let reject = !rejector ? v => !!v : (v, i, a) => !rejector(v, i, a); return this.transform(values => values != null ? values.filter(reject) : values); } describe(options) { const next = (options ? this.resolve(options) : this).clone(); const base = super.describe(options); if (next.innerType) { var _innerOptions; let innerOptions = options; if ((_innerOptions = innerOptions) != null && _innerOptions.value) { innerOptions = Object.assign({}, innerOptions, { parent: innerOptions.value, value: innerOptions.value[0] }); } base.innerType = next.innerType.describe(innerOptions); } return base; } } create$2.prototype = ArraySchema.prototype; // @ts-ignore function create$1(schemas) { return new TupleSchema(schemas); } class TupleSchema extends Schema { constructor(schemas) { super({ type: 'tuple', spec: { types: schemas }, check(v) { const types = this.spec.types; return Array.isArray(v) && v.length === types.length; } }); this.withMutation(() => { this.typeError(tuple.notType); }); } _cast(inputValue, options) { const { types } = this.spec; const value = super._cast(inputValue, options); if (!this._typeCheck(value)) { return value; } let isChanged = false; const castArray = types.map((type, idx) => { const castElement = type.cast(value[idx], Object.assign({}, options, { path: `${options.path || ''}[${idx}]` })); if (castElement !== value[idx]) isChanged = true; return castElement; }); return isChanged ? castArray : value; } _validate(_value, options = {}, panic, next) { let itemTypes = this.spec.types; super._validate(_value, options, panic, (tupleErrors, value) => { var _options$originalValu2; // intentionally not respecting recursive if (!this._typeCheck(value)) { next(tupleErrors, value); return; } let tests = []; for (let [index, itemSchema] of itemTypes.entries()) { var _options$originalValu; tests[index] = itemSchema.asNestedTest({ options, index, parent: value, parentPath: options.path, originalParent: (_options$originalValu = options.originalValue) != null ? _options$originalValu : _value }); } this.runTests({ value, tests, originalValue: (_options$originalValu2 = options.originalValue) != null ? _options$originalValu2 : _value, options }, panic, innerTypeErrors => next(innerTypeErrors.concat(tupleErrors), value)); }); } describe(options) { const next = (options ? this.resolve(options) : this).clone(); const base = super.describe(options); base.innerType = next.spec.types.map((schema, index) => { var _innerOptions; let innerOptions = options; if ((_innerOptions = innerOptions) != null && _innerOptions.value) { innerOptions = Object.assign({}, innerOptions, { parent: innerOptions.value, value: innerOptions.value[index] }); } return schema.describe(innerOptions); }); return base; } } create$1.prototype = TupleSchema.prototype; function create(builder) { return new Lazy(builder); } class Lazy { constructor(builder) { this.type = 'lazy'; this.__isYupSchema__ = true; this.spec = void 0; this._resolve = (value, options = {}) => { let schema = this.builder(value, options); if (!isSchema(schema)) throw new TypeError('lazy() functions must return a valid schema'); if (this.spec.optional) schema = schema.optional(); return schema.resolve(options); }; this.builder = builder; this.spec = { meta: undefined, optional: false }; } clone(spec) { const next = new Lazy(this.builder); next.spec = Object.assign({}, this.spec, spec); return next; } optionality(optional) { const next = this.clone({ optional }); return next; } optional() { return this.optionality(true); } resolve(options) { return this._resolve(options.value, options); } cast(value, options) { return this._resolve(value, options).cast(value, options); } asNestedTest(config) { let { key, index, parent, options } = config; let value = parent[index != null ? index : key]; return this._resolve(value, Object.assign({}, options, { value, parent })).asNestedTest(config); } validate(value, options) { return this._resolve(value, options).validate(value, options); } validateSync(value, options) { return this._resolve(value, options).validateSync(value, options); } validateAt(path, value, options) { return this._resolve(value, options).validateAt(path, value, options); } validateSyncAt(path, value, options) { return this._resolve(value, options).validateSyncAt(path, value, options); } isValid(value, options) { return this._resolve(value, options).isValid(value, options); } isValidSync(value, options) { return this._resolve(value, options).isValidSync(value, options); } describe(options) { return options ? this.resolve(options).describe(options) : { type: 'lazy', meta: this.spec.meta, label: undefined }; } meta(...args) { if (args.length === 0) return this.spec.meta; let next = this.clone(); next.spec.meta = Object.assign(next.spec.meta || {}, args[0]); return next; } } function setLocale(custom) { Object.keys(custom).forEach(type => { // @ts-ignore Object.keys(custom[type]).forEach(method => { // @ts-ignore locale[type][method] = custom[type][method]; }); }); } function addMethod(schemaType, name, fn) { if (!schemaType || !isSchema(schemaType.prototype)) throw new TypeError('You must provide a yup schema constructor function'); if (typeof name !== 'string') throw new TypeError('A Method name must be provided'); if (typeof fn !== 'function') throw new TypeError('Method function must be provided'); schemaType.prototype[name] = fn; } exports.ArraySchema = ArraySchema; exports.BooleanSchema = BooleanSchema; exports.DateSchema = DateSchema; exports.MixedSchema = MixedSchema; exports.NumberSchema = NumberSchema; exports.ObjectSchema = ObjectSchema; exports.Schema = Schema; exports.StringSchema = StringSchema; exports.TupleSchema = TupleSchema; exports.ValidationError = ValidationError; exports.addMethod = addMethod; exports.array = create$2; exports.bool = create$7; exports.boolean = create$7; exports.date = create$4; exports.defaultLocale = locale; exports.getIn = getIn; exports.isSchema = isSchema; exports.lazy = create; exports.mixed = create$8; exports.number = create$5; exports.object = create$3; exports.printValue = printValue; exports.reach = reach; exports.ref = create$9; exports.setLocale = setLocale; exports.string = create$6; exports.tuple = create$1;