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.
		
		
		
		
		
			
		
			
				
					
					
						
							322 lines
						
					
					
						
							9.2 KiB
						
					
					
				
			
		
		
	
	
							322 lines
						
					
					
						
							9.2 KiB
						
					
					
				"use strict"; | 
						|
 | 
						|
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); | 
						|
 | 
						|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); | 
						|
 | 
						|
exports.__esModule = true; | 
						|
exports.default = ObjectSchema; | 
						|
 | 
						|
var _taggedTemplateLiteralLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteralLoose")); | 
						|
 | 
						|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); | 
						|
 | 
						|
var _has = _interopRequireDefault(require("lodash/has")); | 
						|
 | 
						|
var _snakeCase2 = _interopRequireDefault(require("lodash/snakeCase")); | 
						|
 | 
						|
var _camelCase2 = _interopRequireDefault(require("lodash/camelCase")); | 
						|
 | 
						|
var _mapKeys = _interopRequireDefault(require("lodash/mapKeys")); | 
						|
 | 
						|
var _mapValues = _interopRequireDefault(require("lodash/mapValues")); | 
						|
 | 
						|
var _propertyExpr = require("property-expr"); | 
						|
 | 
						|
var _mixed = _interopRequireDefault(require("./mixed")); | 
						|
 | 
						|
var _locale = require("./locale.js"); | 
						|
 | 
						|
var _sortFields = _interopRequireDefault(require("./util/sortFields")); | 
						|
 | 
						|
var _sortByKeyOrder = _interopRequireDefault(require("./util/sortByKeyOrder")); | 
						|
 | 
						|
var _inherits = _interopRequireDefault(require("./util/inherits")); | 
						|
 | 
						|
var _makePath = _interopRequireDefault(require("./util/makePath")); | 
						|
 | 
						|
var _runValidations = _interopRequireWildcard(require("./util/runValidations")); | 
						|
 | 
						|
function _templateObject2() { | 
						|
  var data = (0, _taggedTemplateLiteralLoose2.default)(["", ".", ""]); | 
						|
 | 
						|
  _templateObject2 = function _templateObject2() { | 
						|
    return data; | 
						|
  }; | 
						|
 | 
						|
  return data; | 
						|
} | 
						|
 | 
						|
function _templateObject() { | 
						|
  var data = (0, _taggedTemplateLiteralLoose2.default)(["", ".", ""]); | 
						|
 | 
						|
  _templateObject = function _templateObject() { | 
						|
    return data; | 
						|
  }; | 
						|
 | 
						|
  return data; | 
						|
} | 
						|
 | 
						|
var isObject = function isObject(obj) { | 
						|
  return Object.prototype.toString.call(obj) === '[object Object]'; | 
						|
}; | 
						|
 | 
						|
function unknown(ctx, value) { | 
						|
  var known = Object.keys(ctx.fields); | 
						|
  return Object.keys(value).filter(function (key) { | 
						|
    return known.indexOf(key) === -1; | 
						|
  }); | 
						|
} | 
						|
 | 
						|
function ObjectSchema(spec) { | 
						|
  var _this2 = this; | 
						|
 | 
						|
  if (!(this instanceof ObjectSchema)) return new ObjectSchema(spec); | 
						|
 | 
						|
  _mixed.default.call(this, { | 
						|
    type: 'object', | 
						|
    default: function _default() { | 
						|
      var _this = this; | 
						|
 | 
						|
      if (!this._nodes.length) return undefined; | 
						|
      var dft = {}; | 
						|
 | 
						|
      this._nodes.forEach(function (key) { | 
						|
        dft[key] = _this.fields[key].default ? _this.fields[key].default() : undefined; | 
						|
      }); | 
						|
 | 
						|
      return dft; | 
						|
    } | 
						|
  }); | 
						|
 | 
						|
  this.fields = Object.create(null); | 
						|
  this._nodes = []; | 
						|
  this._excludedEdges = []; | 
						|
  this.withMutation(function () { | 
						|
    _this2.transform(function coerce(value) { | 
						|
      if (typeof value === 'string') { | 
						|
        try { | 
						|
          value = JSON.parse(value); | 
						|
        } catch (err) { | 
						|
          value = null; | 
						|
        } | 
						|
      } | 
						|
 | 
						|
      if (this.isType(value)) return value; | 
						|
      return null; | 
						|
    }); | 
						|
 | 
						|
    if (spec) { | 
						|
      _this2.shape(spec); | 
						|
    } | 
						|
  }); | 
						|
} | 
						|
 | 
						|
(0, _inherits.default)(ObjectSchema, _mixed.default, { | 
						|
  _typeCheck: function _typeCheck(value) { | 
						|
    return isObject(value) || typeof value === 'function'; | 
						|
  }, | 
						|
  _cast: function _cast(_value, options) { | 
						|
    var _this3 = this; | 
						|
 | 
						|
    if (options === void 0) { | 
						|
      options = {}; | 
						|
    } | 
						|
 | 
						|
    var value = _mixed.default.prototype._cast.call(this, _value, options); //should ignore nulls here | 
						|
 | 
						|
 | 
						|
    if (value === undefined) return this.default(); | 
						|
    if (!this._typeCheck(value)) return value; | 
						|
    var fields = this.fields; | 
						|
    var strip = this._option('stripUnknown', options) === true; | 
						|
 | 
						|
    var props = this._nodes.concat(Object.keys(value).filter(function (v) { | 
						|
      return _this3._nodes.indexOf(v) === -1; | 
						|
    })); | 
						|
 | 
						|
    var intermediateValue = {}; // is filled during the transform below | 
						|
 | 
						|
    var innerOptions = (0, _extends2.default)({}, options, { | 
						|
      parent: intermediateValue, | 
						|
      __validating: false | 
						|
    }); | 
						|
    var isChanged = false; | 
						|
    props.forEach(function (prop) { | 
						|
      var field = fields[prop]; | 
						|
      var exists = (0, _has.default)(value, prop); | 
						|
 | 
						|
      if (field) { | 
						|
        var fieldValue; | 
						|
        var strict = field._options && field._options.strict; // safe to mutate since this is fired in sequence | 
						|
 | 
						|
        innerOptions.path = (0, _makePath.default)(_templateObject(), options.path, prop); | 
						|
        innerOptions.value = value[prop]; | 
						|
        field = field.resolve(innerOptions); | 
						|
 | 
						|
        if (field._strip === true) { | 
						|
          isChanged = isChanged || prop in value; | 
						|
          return; | 
						|
        } | 
						|
 | 
						|
        fieldValue = !options.__validating || !strict ? field.cast(value[prop], innerOptions) : value[prop]; | 
						|
        if (fieldValue !== undefined) intermediateValue[prop] = fieldValue; | 
						|
      } else if (exists && !strip) intermediateValue[prop] = value[prop]; | 
						|
 | 
						|
      if (intermediateValue[prop] !== value[prop]) isChanged = true; | 
						|
    }); | 
						|
    return isChanged ? intermediateValue : value; | 
						|
  }, | 
						|
  _validate: function _validate(_value, opts) { | 
						|
    var _this4 = this; | 
						|
 | 
						|
    if (opts === void 0) { | 
						|
      opts = {}; | 
						|
    } | 
						|
 | 
						|
    var endEarly, recursive; | 
						|
    var sync = opts.sync; | 
						|
    var errors = []; | 
						|
    var originalValue = opts.originalValue != null ? opts.originalValue : _value; | 
						|
    endEarly = this._option('abortEarly', opts); | 
						|
    recursive = this._option('recursive', opts); | 
						|
    opts = (0, _extends2.default)({}, opts, { | 
						|
      __validating: true, | 
						|
      originalValue: originalValue | 
						|
    }); | 
						|
    return _mixed.default.prototype._validate.call(this, _value, opts).catch((0, _runValidations.propagateErrors)(endEarly, errors)).then(function (value) { | 
						|
      if (!recursive || !isObject(value)) { | 
						|
        // only iterate though actual objects | 
						|
        if (errors.length) throw errors[0]; | 
						|
        return value; | 
						|
      } | 
						|
 | 
						|
      originalValue = originalValue || value; | 
						|
 | 
						|
      var validations = _this4._nodes.map(function (key) { | 
						|
        var path = (0, _makePath.default)(_templateObject2(), opts.path, key); | 
						|
        var field = _this4.fields[key]; | 
						|
        var innerOptions = (0, _extends2.default)({}, opts, { | 
						|
          path: path, | 
						|
          parent: value, | 
						|
          originalValue: originalValue[key] | 
						|
        }); | 
						|
 | 
						|
        if (field && field.validate) { | 
						|
          // inner fields are always strict: | 
						|
          // 1. this isn't strict so the casting will also have cast inner values | 
						|
          // 2. this is strict in which case the nested values weren't cast either | 
						|
          innerOptions.strict = true; | 
						|
          return field.validate(value[key], innerOptions); | 
						|
        } | 
						|
 | 
						|
        return Promise.resolve(true); | 
						|
      }); | 
						|
 | 
						|
      return (0, _runValidations.default)({ | 
						|
        sync: sync, | 
						|
        validations: validations, | 
						|
        value: value, | 
						|
        errors: errors, | 
						|
        endEarly: endEarly, | 
						|
        path: opts.path, | 
						|
        sort: (0, _sortByKeyOrder.default)(_this4.fields) | 
						|
      }); | 
						|
    }); | 
						|
  }, | 
						|
  concat: function concat(schema) { | 
						|
    var next = _mixed.default.prototype.concat.call(this, schema); | 
						|
 | 
						|
    next._nodes = (0, _sortFields.default)(next.fields, next._excludedEdges); | 
						|
    return next; | 
						|
  }, | 
						|
  shape: function shape(schema, excludes) { | 
						|
    if (excludes === void 0) { | 
						|
      excludes = []; | 
						|
    } | 
						|
 | 
						|
    var next = this.clone(); | 
						|
    var fields = (0, _extends2.default)(next.fields, schema); | 
						|
    next.fields = fields; | 
						|
 | 
						|
    if (excludes.length) { | 
						|
      if (!Array.isArray(excludes[0])) excludes = [excludes]; | 
						|
      var keys = excludes.map(function (_ref) { | 
						|
        var first = _ref[0], | 
						|
            second = _ref[1]; | 
						|
        return first + "-" + second; | 
						|
      }); | 
						|
      next._excludedEdges = next._excludedEdges.concat(keys); | 
						|
    } | 
						|
 | 
						|
    next._nodes = (0, _sortFields.default)(fields, next._excludedEdges); | 
						|
    return next; | 
						|
  }, | 
						|
  from: function from(_from, to, alias) { | 
						|
    var fromGetter = (0, _propertyExpr.getter)(_from, true); | 
						|
    return this.transform(function (obj) { | 
						|
      if (obj == null) return obj; | 
						|
      var newObj = obj; | 
						|
 | 
						|
      if ((0, _has.default)(obj, _from)) { | 
						|
        newObj = (0, _extends2.default)({}, obj); | 
						|
        if (!alias) delete newObj[_from]; | 
						|
        newObj[to] = fromGetter(obj); | 
						|
      } | 
						|
 | 
						|
      return newObj; | 
						|
    }); | 
						|
  }, | 
						|
  noUnknown: function noUnknown(noAllow, message) { | 
						|
    if (noAllow === void 0) { | 
						|
      noAllow = true; | 
						|
    } | 
						|
 | 
						|
    if (message === void 0) { | 
						|
      message = _locale.object.noUnknown; | 
						|
    } | 
						|
 | 
						|
    if (typeof noAllow === 'string') { | 
						|
      message = noAllow; | 
						|
      noAllow = true; | 
						|
    } | 
						|
 | 
						|
    var next = this.test({ | 
						|
      name: 'noUnknown', | 
						|
      exclusive: true, | 
						|
      message: message, | 
						|
      test: function test(value) { | 
						|
        return value == null || !noAllow || unknown(this.schema, value).length === 0; | 
						|
      } | 
						|
    }); | 
						|
    if (noAllow) next._options.stripUnknown = true; | 
						|
    return next; | 
						|
  }, | 
						|
  transformKeys: function transformKeys(fn) { | 
						|
    return this.transform(function (obj) { | 
						|
      return obj && (0, _mapKeys.default)(obj, function (_, key) { | 
						|
        return fn(key); | 
						|
      }); | 
						|
    }); | 
						|
  }, | 
						|
  camelCase: function camelCase() { | 
						|
    return this.transformKeys(_camelCase2.default); | 
						|
  }, | 
						|
  snakeCase: function snakeCase() { | 
						|
    return this.transformKeys(_snakeCase2.default); | 
						|
  }, | 
						|
  constantCase: function constantCase() { | 
						|
    return this.transformKeys(function (key) { | 
						|
      return (0, _snakeCase2.default)(key).toUpperCase(); | 
						|
    }); | 
						|
  }, | 
						|
  describe: function describe() { | 
						|
    var base = _mixed.default.prototype.describe.call(this); | 
						|
 | 
						|
    base.fields = (0, _mapValues.default)(this.fields, function (value) { | 
						|
      return value.describe(); | 
						|
    }); | 
						|
    return base; | 
						|
  } | 
						|
}); | 
						|
module.exports = exports["default"]; |