import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2"; import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray"; import _typeof from "@babel/runtime/helpers/esm/typeof"; import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck"; import _createClass from "@babel/runtime/helpers/esm/createClass"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import { messages as defaultMessages, newMessages } from "./messages"; import { asyncMap, complementError, convertFieldsError, deepMerge, format, warning } from "./util"; import validators from "./validator/index"; export * from "./interface"; /** * Encapsulates a validation schema. * * @param descriptor An object declaring validation rules * for this schema. */ var Schema = /*#__PURE__*/function () { function Schema(descriptor) { _classCallCheck(this, Schema); // ======================== Instance ======================== _defineProperty(this, "rules", null); _defineProperty(this, "_messages", defaultMessages); this.define(descriptor); } _createClass(Schema, [{ key: "define", value: function define(rules) { var _this = this; if (!rules) { throw new Error('Cannot configure a schema with no rules'); } if (_typeof(rules) !== 'object' || Array.isArray(rules)) { throw new Error('Rules must be an object'); } this.rules = {}; Object.keys(rules).forEach(function (name) { var item = rules[name]; _this.rules[name] = Array.isArray(item) ? item : [item]; }); } }, { key: "messages", value: function messages(_messages) { if (_messages) { this._messages = deepMerge(newMessages(), _messages); } return this._messages; } }, { key: "validate", value: function validate(source_) { var _this2 = this; var o = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var oc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {}; var source = source_; var options = o; var callback = oc; if (typeof options === 'function') { callback = options; options = {}; } if (!this.rules || Object.keys(this.rules).length === 0) { if (callback) { callback(null, source); } return Promise.resolve(source); } function complete(results) { var errors = []; var fields = {}; function add(e) { if (Array.isArray(e)) { var _errors; errors = (_errors = errors).concat.apply(_errors, _toConsumableArray(e)); } else { errors.push(e); } } for (var i = 0; i < results.length; i++) { add(results[i]); } if (!errors.length) { callback(null, source); } else { fields = convertFieldsError(errors); callback(errors, fields); } } if (options.messages) { var messages = this.messages(); if (messages === defaultMessages) { messages = newMessages(); } deepMerge(messages, options.messages); options.messages = messages; } else { options.messages = this.messages(); } var series = {}; var keys = options.keys || Object.keys(this.rules); keys.forEach(function (z) { var arr = _this2.rules[z]; var value = source[z]; arr.forEach(function (r) { var rule = r; if (typeof rule.transform === 'function') { if (source === source_) { source = _objectSpread({}, source); } value = source[z] = rule.transform(value); if (value !== undefined && value !== null) { rule.type = rule.type || (Array.isArray(value) ? 'array' : _typeof(value)); } } if (typeof rule === 'function') { rule = { validator: rule }; } else { rule = _objectSpread({}, rule); } // Fill validator. Skip if nothing need to validate rule.validator = _this2.getValidationMethod(rule); if (!rule.validator) { return; } rule.field = z; rule.fullField = rule.fullField || z; rule.type = _this2.getType(rule); series[z] = series[z] || []; series[z].push({ rule: rule, value: value, source: source, field: z }); }); }); var errorFields = {}; return asyncMap(series, options, function (data, doIt) { var rule = data.rule; var deep = (rule.type === 'object' || rule.type === 'array') && (_typeof(rule.fields) === 'object' || _typeof(rule.defaultField) === 'object'); deep = deep && (rule.required || !rule.required && data.value); rule.field = data.field; function addFullField(key, schema) { return _objectSpread(_objectSpread({}, schema), {}, { fullField: "".concat(rule.fullField, ".").concat(key), fullFields: rule.fullFields ? [].concat(_toConsumableArray(rule.fullFields), [key]) : [key] }); } function cb() { var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var errorList = Array.isArray(e) ? e : [e]; if (!options.suppressWarning && errorList.length) { Schema.warning('async-validator:', errorList); } if (errorList.length && rule.message !== undefined) { errorList = [].concat(rule.message); } // Fill error info var filledErrors = errorList.map(complementError(rule, source)); if (options.first && filledErrors.length) { errorFields[rule.field] = 1; return doIt(filledErrors); } if (!deep) { doIt(filledErrors); } else { // if rule is required but the target object // does not exist fail at the rule level and don't // go deeper if (rule.required && !data.value) { if (rule.message !== undefined) { filledErrors = [].concat(rule.message).map(complementError(rule, source)); } else if (options.error) { filledErrors = [options.error(rule, format(options.messages.required, rule.field))]; } return doIt(filledErrors); } var fieldsSchema = {}; if (rule.defaultField) { Object.keys(data.value).map(function (key) { fieldsSchema[key] = rule.defaultField; }); } fieldsSchema = _objectSpread(_objectSpread({}, fieldsSchema), data.rule.fields); var paredFieldsSchema = {}; Object.keys(fieldsSchema).forEach(function (field) { var fieldSchema = fieldsSchema[field]; var fieldSchemaList = Array.isArray(fieldSchema) ? fieldSchema : [fieldSchema]; paredFieldsSchema[field] = fieldSchemaList.map(addFullField.bind(null, field)); }); var schema = new Schema(paredFieldsSchema); schema.messages(options.messages); if (data.rule.options) { data.rule.options.messages = options.messages; data.rule.options.error = options.error; } schema.validate(data.value, data.rule.options || options, function (errs) { var finalErrors = []; if (filledErrors && filledErrors.length) { finalErrors.push.apply(finalErrors, _toConsumableArray(filledErrors)); } if (errs && errs.length) { finalErrors.push.apply(finalErrors, _toConsumableArray(errs)); } doIt(finalErrors.length ? finalErrors : null); }); } } var res; if (rule.asyncValidator) { res = rule.asyncValidator(rule, data.value, cb, data.source, options); } else if (rule.validator) { try { res = rule.validator(rule, data.value, cb, data.source, options); } catch (error) { var _console$error, _console; (_console$error = (_console = console).error) === null || _console$error === void 0 || _console$error.call(_console, error); // rethrow to report error if (!options.suppressValidatorError) { setTimeout(function () { throw error; }, 0); } cb(error.message); } if (res === true) { cb(); } else if (res === false) { cb(typeof rule.message === 'function' ? rule.message(rule.fullField || rule.field) : rule.message || "".concat(rule.fullField || rule.field, " fails")); } else if (res instanceof Array) { cb(res); } else if (res instanceof Error) { cb(res.message); } } if (res && res.then) { res.then(function () { return cb(); }, function (e) { return cb(e); }); } }, function (results) { complete(results); }, source); } }, { key: "getType", value: function getType(rule) { if (rule.type === undefined && rule.pattern instanceof RegExp) { rule.type = 'pattern'; } if (typeof rule.validator !== 'function' && rule.type && !validators.hasOwnProperty(rule.type)) { throw new Error(format('Unknown rule type %s', rule.type)); } return rule.type || 'string'; } }, { key: "getValidationMethod", value: function getValidationMethod(rule) { if (typeof rule.validator === 'function') { return rule.validator; } var keys = Object.keys(rule); var messageIndex = keys.indexOf('message'); if (messageIndex !== -1) { keys.splice(messageIndex, 1); } if (keys.length === 1 && keys[0] === 'required') { return validators.required; } return validators[this.getType(rule)] || undefined; } }]); return Schema; }(); // ========================= Static ========================= _defineProperty(Schema, "register", function register(type, validator) { if (typeof validator !== 'function') { throw new Error('Cannot register a validator by type, validator is not a function'); } validators[type] = validator; }); _defineProperty(Schema, "warning", warning); _defineProperty(Schema, "messages", defaultMessages); _defineProperty(Schema, "validators", validators); export default Schema;