You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							559 lines
						
					
					
						
							15 KiB
						
					
					
				
			
		
		
	
	
							559 lines
						
					
					
						
							15 KiB
						
					
					
				"use strict"; | 
						|
 | 
						|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | 
						|
 | 
						|
exports.__esModule = true; | 
						|
exports.default = SchemaType; | 
						|
 | 
						|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); | 
						|
 | 
						|
var _has = _interopRequireDefault(require("lodash/has")); | 
						|
 | 
						|
var _cloneDeepWith = _interopRequireDefault(require("lodash/cloneDeepWith")); | 
						|
 | 
						|
var _toArray2 = _interopRequireDefault(require("lodash/toArray")); | 
						|
 | 
						|
var _locale = require("./locale"); | 
						|
 | 
						|
var _Condition = _interopRequireDefault(require("./Condition")); | 
						|
 | 
						|
var _runValidations = _interopRequireDefault(require("./util/runValidations")); | 
						|
 | 
						|
var _merge = _interopRequireDefault(require("./util/merge")); | 
						|
 | 
						|
var _isSchema = _interopRequireDefault(require("./util/isSchema")); | 
						|
 | 
						|
var _isAbsent = _interopRequireDefault(require("./util/isAbsent")); | 
						|
 | 
						|
var _createValidation = _interopRequireDefault(require("./util/createValidation")); | 
						|
 | 
						|
var _printValue = _interopRequireDefault(require("./util/printValue")); | 
						|
 | 
						|
var _Reference = _interopRequireDefault(require("./Reference")); | 
						|
 | 
						|
var _reach = require("./util/reach"); | 
						|
 | 
						|
var notEmpty = function notEmpty(value) { | 
						|
  return !(0, _isAbsent.default)(value); | 
						|
}; | 
						|
 | 
						|
var RefSet = | 
						|
/*#__PURE__*/ | 
						|
function () { | 
						|
  function RefSet() { | 
						|
    this.list = new Set(); | 
						|
    this.refs = new Map(); | 
						|
  } | 
						|
 | 
						|
  var _proto = RefSet.prototype; | 
						|
 | 
						|
  _proto.toArray = function toArray() { | 
						|
    return (0, _toArray2.default)(this.list).concat((0, _toArray2.default)(this.refs.values())); | 
						|
  }; | 
						|
 | 
						|
  _proto.add = function add(value) { | 
						|
    _Reference.default.isRef(value) ? this.refs.set(value.key, value) : this.list.add(value); | 
						|
  }; | 
						|
 | 
						|
  _proto.delete = function _delete(value) { | 
						|
    _Reference.default.isRef(value) ? this.refs.delete(value.key, value) : this.list.delete(value); | 
						|
  }; | 
						|
 | 
						|
  _proto.has = function has(value, resolve) { | 
						|
    if (this.list.has(value)) return true; | 
						|
    var item, | 
						|
        values = this.refs.values(); | 
						|
 | 
						|
    while (item = values.next(), !item.done) { | 
						|
      if (resolve(item.value) === value) return true; | 
						|
    } | 
						|
 | 
						|
    return false; | 
						|
  }; | 
						|
 | 
						|
  return RefSet; | 
						|
}(); | 
						|
 | 
						|
function SchemaType(options) { | 
						|
  var _this = this; | 
						|
 | 
						|
  if (options === void 0) { | 
						|
    options = {}; | 
						|
  } | 
						|
 | 
						|
  if (!(this instanceof SchemaType)) return new SchemaType(); | 
						|
  this._deps = []; | 
						|
  this._conditions = []; | 
						|
  this._options = { | 
						|
    abortEarly: true, | 
						|
    recursive: true | 
						|
  }; | 
						|
  this._exclusive = Object.create(null); | 
						|
  this._whitelist = new RefSet(); | 
						|
  this._blacklist = new RefSet(); | 
						|
  this.tests = []; | 
						|
  this.transforms = []; | 
						|
  this.withMutation(function () { | 
						|
    _this.typeError(_locale.mixed.notType); | 
						|
  }); | 
						|
  if ((0, _has.default)(options, 'default')) this._defaultDefault = options.default; | 
						|
  this._type = options.type || 'mixed'; | 
						|
} | 
						|
 | 
						|
var proto = SchemaType.prototype = { | 
						|
  __isYupSchema__: true, | 
						|
  constructor: SchemaType, | 
						|
  clone: function clone() { | 
						|
    var _this2 = this; | 
						|
 | 
						|
    if (this._mutate) return this; // if the nested value is a schema we can skip cloning, since | 
						|
    // they are already immutable | 
						|
 | 
						|
    return (0, _cloneDeepWith.default)(this, function (value) { | 
						|
      if ((0, _isSchema.default)(value) && value !== _this2) return value; | 
						|
    }); | 
						|
  }, | 
						|
  label: function label(_label) { | 
						|
    var next = this.clone(); | 
						|
    next._label = _label; | 
						|
    return next; | 
						|
  }, | 
						|
  meta: function meta(obj) { | 
						|
    if (arguments.length === 0) return this._meta; | 
						|
    var next = this.clone(); | 
						|
    next._meta = (0, _extends2.default)(next._meta || {}, obj); | 
						|
    return next; | 
						|
  }, | 
						|
  withMutation: function withMutation(fn) { | 
						|
    this._mutate = true; | 
						|
    var result = fn(this); | 
						|
    this._mutate = false; | 
						|
    return result; | 
						|
  }, | 
						|
  concat: function concat(schema) { | 
						|
    if (!schema) 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); | 
						|
    var cloned = this.clone(); | 
						|
    var next = (0, _merge.default)(this.clone(), schema.clone()); // undefined isn't merged over, but is a valid value for default | 
						|
 | 
						|
    if ((0, _has.default)(schema, '_default')) next._default = schema._default; | 
						|
    next.tests = cloned.tests; | 
						|
    next._exclusive = cloned._exclusive; // manually add the new tests to ensure | 
						|
    // the deduping logic is consistent | 
						|
 | 
						|
    schema.tests.forEach(function (fn) { | 
						|
      next = next.test(fn.OPTIONS); | 
						|
    }); | 
						|
    next._type = schema._type; | 
						|
    return next; | 
						|
  }, | 
						|
  isType: function isType(v) { | 
						|
    if (this._nullable && v === null) return true; | 
						|
    return !this._typeCheck || this._typeCheck(v); | 
						|
  }, | 
						|
  resolve: function resolve(_ref) { | 
						|
    var context = _ref.context, | 
						|
        parent = _ref.parent; | 
						|
 | 
						|
    if (this._conditions.length) { | 
						|
      return this._conditions.reduce(function (schema, match) { | 
						|
        return match.resolve(schema, match.getValue(parent, context)); | 
						|
      }, this); | 
						|
    } | 
						|
 | 
						|
    return this; | 
						|
  }, | 
						|
  cast: function cast(value, options) { | 
						|
    if (options === void 0) { | 
						|
      options = {}; | 
						|
    } | 
						|
 | 
						|
    var resolvedSchema = this.resolve(options); | 
						|
 | 
						|
    var result = resolvedSchema._cast(value, options); | 
						|
 | 
						|
    if (value !== undefined && options.assert !== false && resolvedSchema.isType(result) !== true) { | 
						|
      var formattedValue = (0, _printValue.default)(value); | 
						|
      var formattedResult = (0, _printValue.default)(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: function _cast(rawValue) { | 
						|
    var _this3 = this; | 
						|
 | 
						|
    var value = rawValue === undefined ? rawValue : this.transforms.reduce(function (value, fn) { | 
						|
      return fn.call(_this3, value, rawValue); | 
						|
    }, rawValue); | 
						|
 | 
						|
    if (value === undefined && (0, _has.default)(this, '_default')) { | 
						|
      value = this.default(); | 
						|
    } | 
						|
 | 
						|
    return value; | 
						|
  }, | 
						|
  _validate: function _validate(_value, options) { | 
						|
    var _this4 = this; | 
						|
 | 
						|
    if (options === void 0) { | 
						|
      options = {}; | 
						|
    } | 
						|
 | 
						|
    var value = _value; | 
						|
    var originalValue = options.originalValue != null ? options.originalValue : _value; | 
						|
 | 
						|
    var isStrict = this._option('strict', options); | 
						|
 | 
						|
    var endEarly = this._option('abortEarly', options); | 
						|
 | 
						|
    var sync = options.sync; | 
						|
    var path = options.path; | 
						|
    var label = this._label; | 
						|
 | 
						|
    if (!isStrict) { | 
						|
      value = this._cast(value, (0, _extends2.default)({ | 
						|
        assert: false | 
						|
      }, options)); | 
						|
    } // value is cast, we can check if it meets type requirements | 
						|
 | 
						|
 | 
						|
    var validationParams = { | 
						|
      value: value, | 
						|
      path: path, | 
						|
      schema: this, | 
						|
      options: options, | 
						|
      label: label, | 
						|
      originalValue: originalValue, | 
						|
      sync: sync | 
						|
    }; | 
						|
    var initialTests = []; | 
						|
    if (this._typeError) initialTests.push(this._typeError(validationParams)); | 
						|
    if (this._whitelistError) initialTests.push(this._whitelistError(validationParams)); | 
						|
    if (this._blacklistError) initialTests.push(this._blacklistError(validationParams)); | 
						|
    return (0, _runValidations.default)({ | 
						|
      validations: initialTests, | 
						|
      endEarly: endEarly, | 
						|
      value: value, | 
						|
      path: path, | 
						|
      sync: sync | 
						|
    }).then(function (value) { | 
						|
      return (0, _runValidations.default)({ | 
						|
        path: path, | 
						|
        sync: sync, | 
						|
        value: value, | 
						|
        endEarly: endEarly, | 
						|
        validations: _this4.tests.map(function (fn) { | 
						|
          return fn(validationParams); | 
						|
        }) | 
						|
      }); | 
						|
    }); | 
						|
  }, | 
						|
  validate: function validate(value, options) { | 
						|
    if (options === void 0) { | 
						|
      options = {}; | 
						|
    } | 
						|
 | 
						|
    var schema = this.resolve(options); | 
						|
    return schema._validate(value, options); | 
						|
  }, | 
						|
  validateSync: function validateSync(value, options) { | 
						|
    if (options === void 0) { | 
						|
      options = {}; | 
						|
    } | 
						|
 | 
						|
    var schema = this.resolve(options); | 
						|
    var result, err; | 
						|
 | 
						|
    schema._validate(value, (0, _extends2.default)({}, options, { | 
						|
      sync: true | 
						|
    })).then(function (r) { | 
						|
      return result = r; | 
						|
    }).catch(function (e) { | 
						|
      return err = e; | 
						|
    }); | 
						|
 | 
						|
    if (err) throw err; | 
						|
    return result; | 
						|
  }, | 
						|
  isValid: function isValid(value, options) { | 
						|
    return this.validate(value, options).then(function () { | 
						|
      return true; | 
						|
    }).catch(function (err) { | 
						|
      if (err.name === 'ValidationError') return false; | 
						|
      throw err; | 
						|
    }); | 
						|
  }, | 
						|
  isValidSync: function isValidSync(value, options) { | 
						|
    try { | 
						|
      this.validateSync(value, (0, _extends2.default)({}, options)); | 
						|
      return true; | 
						|
    } catch (err) { | 
						|
      if (err.name === 'ValidationError') return false; | 
						|
      throw err; | 
						|
    } | 
						|
  }, | 
						|
  getDefault: function getDefault(options) { | 
						|
    if (options === void 0) { | 
						|
      options = {}; | 
						|
    } | 
						|
 | 
						|
    var schema = this.resolve(options); | 
						|
    return schema.default(); | 
						|
  }, | 
						|
  default: function _default(def) { | 
						|
    if (arguments.length === 0) { | 
						|
      var defaultValue = (0, _has.default)(this, '_default') ? this._default : this._defaultDefault; | 
						|
      return typeof defaultValue === 'function' ? defaultValue.call(this) : (0, _cloneDeepWith.default)(defaultValue); | 
						|
    } | 
						|
 | 
						|
    var next = this.clone(); | 
						|
    next._default = def; | 
						|
    return next; | 
						|
  }, | 
						|
  strict: function strict() { | 
						|
    var next = this.clone(); | 
						|
    next._options.strict = true; | 
						|
    return next; | 
						|
  }, | 
						|
  required: function required(message) { | 
						|
    if (message === void 0) { | 
						|
      message = _locale.mixed.required; | 
						|
    } | 
						|
 | 
						|
    return this.test({ | 
						|
      message: message, | 
						|
      name: 'required', | 
						|
      test: notEmpty | 
						|
    }); | 
						|
  }, | 
						|
  notRequired: function notRequired() { | 
						|
    var next = this.clone(); | 
						|
    next.tests = next.tests.filter(function (test) { | 
						|
      return test.OPTIONS.name !== 'required'; | 
						|
    }); | 
						|
    return next; | 
						|
  }, | 
						|
  nullable: function nullable(value) { | 
						|
    var next = this.clone(); | 
						|
    next._nullable = value === false ? false : true; | 
						|
    return next; | 
						|
  }, | 
						|
  transform: function transform(fn) { | 
						|
    var 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: function test() { | 
						|
    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | 
						|
      args[_key] = arguments[_key]; | 
						|
    } | 
						|
 | 
						|
    var opts = args[0]; | 
						|
 | 
						|
    if (args.length > 1) { | 
						|
      var name = args[0], | 
						|
          message = args[1], | 
						|
          test = args[2]; | 
						|
 | 
						|
      if (test == null) { | 
						|
        test = message; | 
						|
        message = _locale.mixed.default; | 
						|
      } | 
						|
 | 
						|
      opts = { | 
						|
        name: name, | 
						|
        test: test, | 
						|
        message: message, | 
						|
        exclusive: false | 
						|
      }; | 
						|
    } | 
						|
 | 
						|
    if (typeof opts.test !== 'function') throw new TypeError('`test` is a required parameters'); | 
						|
    var next = this.clone(); | 
						|
    var validate = (0, _createValidation.default)(opts); | 
						|
    var isExclusive = opts.exclusive || opts.name && next._exclusive[opts.name] === true; | 
						|
 | 
						|
    if (opts.exclusive && !opts.name) { | 
						|
      throw new TypeError('Exclusive tests must provide a unique `name` identifying the test'); | 
						|
    } | 
						|
 | 
						|
    next._exclusive[opts.name] = !!opts.exclusive; | 
						|
    next.tests = next.tests.filter(function (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: function when(keys, options) { | 
						|
    var next = this.clone(), | 
						|
        deps = [].concat(keys).map(function (key) { | 
						|
      return new _Reference.default(key); | 
						|
    }); | 
						|
    deps.forEach(function (dep) { | 
						|
      if (!dep.isContext) next._deps.push(dep.key); | 
						|
    }); | 
						|
 | 
						|
    next._conditions.push(new _Condition.default(deps, options)); | 
						|
 | 
						|
    return next; | 
						|
  }, | 
						|
  typeError: function typeError(message) { | 
						|
    var next = this.clone(); | 
						|
    next._typeError = (0, _createValidation.default)({ | 
						|
      message: message, | 
						|
      name: 'typeError', | 
						|
      test: function test(value) { | 
						|
        if (value !== undefined && !this.schema.isType(value)) return this.createError({ | 
						|
          params: { | 
						|
            type: this.schema._type | 
						|
          } | 
						|
        }); | 
						|
        return true; | 
						|
      } | 
						|
    }); | 
						|
    return next; | 
						|
  }, | 
						|
  oneOf: function oneOf(enums, message) { | 
						|
    if (message === void 0) { | 
						|
      message = _locale.mixed.oneOf; | 
						|
    } | 
						|
 | 
						|
    var next = this.clone(); | 
						|
    enums.forEach(function (val) { | 
						|
      next._whitelist.add(val); | 
						|
 | 
						|
      next._blacklist.delete(val); | 
						|
    }); | 
						|
    next._whitelistError = (0, _createValidation.default)({ | 
						|
      message: message, | 
						|
      name: 'oneOf', | 
						|
      test: function test(value) { | 
						|
        if (value === undefined) return true; | 
						|
        var valids = this.schema._whitelist; | 
						|
        return valids.has(value, this.resolve) ? true : this.createError({ | 
						|
          params: { | 
						|
            values: valids.toArray().join(', ') | 
						|
          } | 
						|
        }); | 
						|
      } | 
						|
    }); | 
						|
    return next; | 
						|
  }, | 
						|
  notOneOf: function notOneOf(enums, message) { | 
						|
    if (message === void 0) { | 
						|
      message = _locale.mixed.notOneOf; | 
						|
    } | 
						|
 | 
						|
    var next = this.clone(); | 
						|
    enums.forEach(function (val) { | 
						|
      next._blacklist.add(val); | 
						|
 | 
						|
      next._whitelist.delete(val); | 
						|
    }); | 
						|
    next._blacklistError = (0, _createValidation.default)({ | 
						|
      message: message, | 
						|
      name: 'notOneOf', | 
						|
      test: function test(value) { | 
						|
        var invalids = this.schema._blacklist; | 
						|
        if (invalids.has(value, this.resolve)) return this.createError({ | 
						|
          params: { | 
						|
            values: invalids.toArray().join(', ') | 
						|
          } | 
						|
        }); | 
						|
        return true; | 
						|
      } | 
						|
    }); | 
						|
    return next; | 
						|
  }, | 
						|
  strip: function strip(_strip) { | 
						|
    if (_strip === void 0) { | 
						|
      _strip = true; | 
						|
    } | 
						|
 | 
						|
    var next = this.clone(); | 
						|
    next._strip = _strip; | 
						|
    return next; | 
						|
  }, | 
						|
  _option: function _option(key, overrides) { | 
						|
    return (0, _has.default)(overrides, key) ? overrides[key] : this._options[key]; | 
						|
  }, | 
						|
  describe: function describe() { | 
						|
    var next = this.clone(); | 
						|
    return { | 
						|
      type: next._type, | 
						|
      meta: next._meta, | 
						|
      label: next._label, | 
						|
      tests: next.tests.map(function (fn) { | 
						|
        return { | 
						|
          name: fn.OPTIONS.name, | 
						|
          params: fn.OPTIONS.params | 
						|
        }; | 
						|
      }).filter(function (n, idx, list) { | 
						|
        return list.findIndex(function (c) { | 
						|
          return c.name === n.name; | 
						|
        }) === idx; | 
						|
      }) | 
						|
    }; | 
						|
  } | 
						|
}; | 
						|
var _arr = ['validate', 'validateSync']; | 
						|
 | 
						|
var _loop = function _loop() { | 
						|
  var method = _arr[_i]; | 
						|
 | 
						|
  proto[method + "At"] = function (path, value, options) { | 
						|
    if (options === void 0) { | 
						|
      options = {}; | 
						|
    } | 
						|
 | 
						|
    var _getIn = (0, _reach.getIn)(this, path, value, options.context), | 
						|
        parent = _getIn.parent, | 
						|
        parentPath = _getIn.parentPath, | 
						|
        schema = _getIn.schema; | 
						|
 | 
						|
    return schema[method](parent && parent[parentPath], (0, _extends2.default)({}, options, { | 
						|
      parent: parent, | 
						|
      path: path | 
						|
    })); | 
						|
  }; | 
						|
}; | 
						|
 | 
						|
for (var _i = 0; _i < _arr.length; _i++) { | 
						|
  _loop(); | 
						|
} | 
						|
 | 
						|
var _arr2 = ['equals', 'is']; | 
						|
 | 
						|
for (var _i2 = 0; _i2 < _arr2.length; _i2++) { | 
						|
  var alias = _arr2[_i2]; | 
						|
  proto[alias] = proto.oneOf; | 
						|
} | 
						|
 | 
						|
var _arr3 = ['not', 'nope']; | 
						|
 | 
						|
for (var _i3 = 0; _i3 < _arr3.length; _i3++) { | 
						|
  var _alias = _arr3[_i3]; | 
						|
  proto[_alias] = proto.notOneOf; | 
						|
} | 
						|
 | 
						|
module.exports = exports["default"]; |