From 64b432916af9c9218ab3f3eca614e26c542142ae Mon Sep 17 00:00:00 2001 From: jiangping <jp@doumee.com> Date: 星期二, 07 十一月 2023 15:47:13 +0800 Subject: [PATCH] bug --- minipro_standard/uni_modules/uview-ui/libs/util/async-validator.js | 2686 +++++++++++++++++++++++++++++----------------------------- 1 files changed, 1,343 insertions(+), 1,343 deletions(-) diff --git a/minipro_standard/uni_modules/uview-ui/libs/util/async-validator.js b/minipro_standard/uni_modules/uview-ui/libs/util/async-validator.js index 5facbde..9e114df 100644 --- a/minipro_standard/uni_modules/uview-ui/libs/util/async-validator.js +++ b/minipro_standard/uni_modules/uview-ui/libs/util/async-validator.js @@ -1,1343 +1,1343 @@ -function _extends() { - _extends = Object.assign || function (target) { - for (let i = 1; i < arguments.length; i++) { - const source = arguments[i] - - for (const key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key] - } - } - } - - return target - } - - return _extends.apply(this, arguments) -} - -/* eslint no-console:0 */ -const formatRegExp = /%[sdj%]/g -let warning = function warning() {} // don't print warning message when in production env or node runtime - -if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV !== 'production' && typeof window - !== 'undefined' && typeof document !== 'undefined') { - warning = function warning(type, errors) { - if (typeof console !== 'undefined' && console.warn) { - if (errors.every((e) => typeof e === 'string')) { - console.warn(type, errors) - } - } - } -} - -function convertFieldsError(errors) { - if (!errors || !errors.length) return null - const fields = {} - errors.forEach((error) => { - const { field } = error - fields[field] = fields[field] || [] - fields[field].push(error) - }) - return fields -} - -function format() { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key] - } - - let i = 1 - const f = args[0] - const len = args.length - - if (typeof f === 'function') { - return f.apply(null, args.slice(1)) - } - - if (typeof f === 'string') { - let str = String(f).replace(formatRegExp, (x) => { - if (x === '%%') { - return '%' - } - - if (i >= len) { - return x - } - - switch (x) { - case '%s': - return String(args[i++]) - - case '%d': - return Number(args[i++]) - - case '%j': - try { - return JSON.stringify(args[i++]) - } catch (_) { - return '[Circular]' - } - - break - - default: - return x - } - }) - - for (let arg = args[i]; i < len; arg = args[++i]) { - str += ` ${arg}` - } - - return str - } - - return f -} - -function isNativeStringType(type) { - return type === 'string' || type === 'url' || type === 'hex' || type === 'email' || type === 'pattern' -} - -function isEmptyValue(value, type) { - if (value === undefined || value === null) { - return true - } - - if (type === 'array' && Array.isArray(value) && !value.length) { - return true - } - - if (isNativeStringType(type) && typeof value === 'string' && !value) { - return true - } - - return false -} - -function asyncParallelArray(arr, func, callback) { - const results = [] - let total = 0 - const arrLength = arr.length - - function count(errors) { - results.push.apply(results, errors) - total++ - - if (total === arrLength) { - callback(results) - } - } - - arr.forEach((a) => { - func(a, count) - }) -} - -function asyncSerialArray(arr, func, callback) { - let index = 0 - const arrLength = arr.length - - function next(errors) { - if (errors && errors.length) { - callback(errors) - return - } - - const original = index - index += 1 - - if (original < arrLength) { - func(arr[original], next) - } else { - callback([]) - } - } - - next([]) -} - -function flattenObjArr(objArr) { - const ret = [] - Object.keys(objArr).forEach((k) => { - ret.push.apply(ret, objArr[k]) - }) - return ret -} - -function asyncMap(objArr, option, func, callback) { - if (option.first) { - const _pending = new Promise((resolve, reject) => { - const next = function next(errors) { - callback(errors) - return errors.length ? reject({ - errors, - fields: convertFieldsError(errors) - }) : resolve() - } - - const flattenArr = flattenObjArr(objArr) - asyncSerialArray(flattenArr, func, next) - }) - - _pending.catch((e) => e) - - return _pending - } - - let firstFields = option.firstFields || [] - - if (firstFields === true) { - firstFields = Object.keys(objArr) - } - - const objArrKeys = Object.keys(objArr) - const objArrLength = objArrKeys.length - let total = 0 - const results = [] - const pending = new Promise((resolve, reject) => { - const next = function next(errors) { - results.push.apply(results, errors) - total++ - - if (total === objArrLength) { - callback(results) - return results.length ? reject({ - errors: results, - fields: convertFieldsError(results) - }) : resolve() - } - } - - if (!objArrKeys.length) { - callback(results) - resolve() - } - - objArrKeys.forEach((key) => { - const arr = objArr[key] - - if (firstFields.indexOf(key) !== -1) { - asyncSerialArray(arr, func, next) - } else { - asyncParallelArray(arr, func, next) - } - }) - }) - pending.catch((e) => e) - return pending -} - -function complementError(rule) { - return function (oe) { - if (oe && oe.message) { - oe.field = oe.field || rule.fullField - return oe - } - - return { - message: typeof oe === 'function' ? oe() : oe, - field: oe.field || rule.fullField - } - } -} - -function deepMerge(target, source) { - if (source) { - for (const s in source) { - if (source.hasOwnProperty(s)) { - const value = source[s] - - if (typeof value === 'object' && typeof target[s] === 'object') { - target[s] = { ...target[s], ...value } - } else { - target[s] = value - } - } - } - } - - return target -} - -/** - * Rule for validating required fields. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param source The source object being validated. - * @param errors An array of errors that this rule may add - * validation errors to. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function required(rule, value, source, errors, options, type) { - if (rule.required && (!source.hasOwnProperty(rule.field) || isEmptyValue(value, type || rule.type))) { - errors.push(format(options.messages.required, rule.fullField)) - } -} - -/** - * Rule for validating whitespace. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param source The source object being validated. - * @param errors An array of errors that this rule may add - * validation errors to. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function whitespace(rule, value, source, errors, options) { - if (/^\s+$/.test(value) || value === '') { - errors.push(format(options.messages.whitespace, rule.fullField)) - } -} - -/* eslint max-len:0 */ - -const pattern = { - // http://emailregex.com/ - email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, - url: new RegExp( - '^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$', - 'i' - ), - hex: /^#?([a-f0-9]{6}|[a-f0-9]{3})$/i -} -var types = { - integer: function integer(value) { - return /^(-)?\d+$/.test(value); - }, - float: function float(value) { - return /^(-)?\d+(\.\d+)?$/.test(value); - }, - array: function array(value) { - return Array.isArray(value) - }, - regexp: function regexp(value) { - if (value instanceof RegExp) { - return true - } - - try { - return !!new RegExp(value) - } catch (e) { - return false - } - }, - date: function date(value) { - return typeof value.getTime === 'function' && typeof value.getMonth === 'function' && typeof value.getYear - === 'function' - }, - number: function number(value) { - if (isNaN(value)) { - return false - } - - // 淇敼婧愮爜锛屽皢瀛楃涓叉暟鍊煎厛杞负鏁板�� - return typeof +value === 'number' - }, - object: function object(value) { - return typeof value === 'object' && !types.array(value) - }, - method: function method(value) { - return typeof value === 'function' - }, - email: function email(value) { - return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255 - }, - url: function url(value) { - return typeof value === 'string' && !!value.match(pattern.url) - }, - hex: function hex(value) { - return typeof value === 'string' && !!value.match(pattern.hex) - } -} -/** - * Rule for validating the type of a value. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param source The source object being validated. - * @param errors An array of errors that this rule may add - * validation errors to. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function type(rule, value, source, errors, options) { - if (rule.required && value === undefined) { - required(rule, value, source, errors, options) - return - } - - const custom = ['integer', 'float', 'array', 'regexp', 'object', 'method', 'email', 'number', 'date', 'url', 'hex'] - const ruleType = rule.type - - if (custom.indexOf(ruleType) > -1) { - if (!types[ruleType](value)) { - errors.push(format(options.messages.types[ruleType], rule.fullField, rule.type)) - } // straight typeof check - } else if (ruleType && typeof value !== rule.type) { - errors.push(format(options.messages.types[ruleType], rule.fullField, rule.type)) - } -} - -/** - * Rule for validating minimum and maximum allowed values. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param source The source object being validated. - * @param errors An array of errors that this rule may add - * validation errors to. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function range(rule, value, source, errors, options) { - const len = typeof rule.len === 'number' - const min = typeof rule.min === 'number' - const max = typeof rule.max === 'number' // 姝e垯鍖归厤鐮佺偣鑼冨洿浠嶶+010000涓�鐩村埌U+10FFFF鐨勬枃瀛楋紙琛ュ厖骞抽潰Supplementary Plane锛� - - const spRegexp = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g - let val = value - let key = null - const num = typeof value === 'number' - const str = typeof value === 'string' - const arr = Array.isArray(value) - - if (num) { - key = 'number' - } else if (str) { - key = 'string' - } else if (arr) { - key = 'array' - } // if the value is not of a supported type for range validation - // the validation rule rule should use the - // type property to also test for a particular type - - if (!key) { - return false - } - - if (arr) { - val = value.length - } - - if (str) { - // 澶勭悊鐮佺偣澶т簬U+010000鐨勬枃瀛條ength灞炴�т笉鍑嗙‘鐨刡ug锛屽"馉馉馉".lenght !== 3 - val = value.replace(spRegexp, '_').length - } - - if (len) { - if (val !== rule.len) { - errors.push(format(options.messages[key].len, rule.fullField, rule.len)) - } - } else if (min && !max && val < rule.min) { - errors.push(format(options.messages[key].min, rule.fullField, rule.min)) - } else if (max && !min && val > rule.max) { - errors.push(format(options.messages[key].max, rule.fullField, rule.max)) - } else if (min && max && (val < rule.min || val > rule.max)) { - errors.push(format(options.messages[key].range, rule.fullField, rule.min, rule.max)) - } -} - -const ENUM = 'enum' -/** - * Rule for validating a value exists in an enumerable list. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param source The source object being validated. - * @param errors An array of errors that this rule may add - * validation errors to. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function enumerable(rule, value, source, errors, options) { - rule[ENUM] = Array.isArray(rule[ENUM]) ? rule[ENUM] : [] - - if (rule[ENUM].indexOf(value) === -1) { - errors.push(format(options.messages[ENUM], rule.fullField, rule[ENUM].join(', '))) - } -} - -/** - * Rule for validating a regular expression pattern. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param source The source object being validated. - * @param errors An array of errors that this rule may add - * validation errors to. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function pattern$1(rule, value, source, errors, options) { - if (rule.pattern) { - if (rule.pattern instanceof RegExp) { - // if a RegExp instance is passed, reset `lastIndex` in case its `global` - // flag is accidentally set to `true`, which in a validation scenario - // is not necessary and the result might be misleading - rule.pattern.lastIndex = 0 - - if (!rule.pattern.test(value)) { - errors.push(format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern)) - } - } else if (typeof rule.pattern === 'string') { - const _pattern = new RegExp(rule.pattern) - - if (!_pattern.test(value)) { - errors.push(format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern)) - } - } - } -} - -const rules = { - required, - whitespace, - type, - range, - enum: enumerable, - pattern: pattern$1 -} - -/** - * Performs validation for string types. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param callback The callback function. - * @param source The source object being validated. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function string(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value, 'string') && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options, 'string') - - if (!isEmptyValue(value, 'string')) { - rules.type(rule, value, source, errors, options) - rules.range(rule, value, source, errors, options) - rules.pattern(rule, value, source, errors, options) - - if (rule.whitespace === true) { - rules.whitespace(rule, value, source, errors, options) - } - } - } - - callback(errors) -} - -/** - * Validates a function. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param callback The callback function. - * @param source The source object being validated. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function method(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value) && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options) - - if (value !== undefined) { - rules.type(rule, value, source, errors, options) - } - } - - callback(errors) -} - -/** - * Validates a number. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param callback The callback function. - * @param source The source object being validated. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function number(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (value === '') { - value = undefined - } - - if (isEmptyValue(value) && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options) - - if (value !== undefined) { - rules.type(rule, value, source, errors, options) - rules.range(rule, value, source, errors, options) - } - } - - callback(errors) -} - -/** - * Validates a boolean. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param callback The callback function. - * @param source The source object being validated. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function _boolean(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value) && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options) - - if (value !== undefined) { - rules.type(rule, value, source, errors, options) - } - } - - callback(errors) -} - -/** - * Validates the regular expression type. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param callback The callback function. - * @param source The source object being validated. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function regexp(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value) && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options) - - if (!isEmptyValue(value)) { - rules.type(rule, value, source, errors, options) - } - } - - callback(errors) -} - -/** - * Validates a number is an integer. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param callback The callback function. - * @param source The source object being validated. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function integer(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value) && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options) - - if (value !== undefined) { - rules.type(rule, value, source, errors, options) - rules.range(rule, value, source, errors, options) - } - } - - callback(errors) -} - -/** - * Validates a number is a floating point number. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param callback The callback function. - * @param source The source object being validated. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function floatFn(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value) && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options) - - if (value !== undefined) { - rules.type(rule, value, source, errors, options) - rules.range(rule, value, source, errors, options) - } - } - - callback(errors) -} - -/** - * Validates an array. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param callback The callback function. - * @param source The source object being validated. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function array(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value, 'array') && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options, 'array') - - if (!isEmptyValue(value, 'array')) { - rules.type(rule, value, source, errors, options) - rules.range(rule, value, source, errors, options) - } - } - - callback(errors) -} - -/** - * Validates an object. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param callback The callback function. - * @param source The source object being validated. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function object(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value) && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options) - - if (value !== undefined) { - rules.type(rule, value, source, errors, options) - } - } - - callback(errors) -} - -const ENUM$1 = 'enum' -/** - * Validates an enumerable list. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param callback The callback function. - * @param source The source object being validated. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function enumerable$1(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value) && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options) - - if (value !== undefined) { - rules[ENUM$1](rule, value, source, errors, options) - } - } - - callback(errors) -} - -/** - * Validates a regular expression pattern. - * - * Performs validation when a rule only contains - * a pattern property but is not declared as a string type. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param callback The callback function. - * @param source The source object being validated. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function pattern$2(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value, 'string') && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options) - - if (!isEmptyValue(value, 'string')) { - rules.pattern(rule, value, source, errors, options) - } - } - - callback(errors) -} - -function date(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value) && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options) - - if (!isEmptyValue(value)) { - let dateObject - - if (typeof value === 'number') { - dateObject = new Date(value) - } else { - dateObject = value - } - - rules.type(rule, dateObject, source, errors, options) - - if (dateObject) { - rules.range(rule, dateObject.getTime(), source, errors, options) - } - } - } - - callback(errors) -} - -function required$1(rule, value, callback, source, options) { - const errors = [] - const type = Array.isArray(value) ? 'array' : typeof value - rules.required(rule, value, source, errors, options, type) - callback(errors) -} - -function type$1(rule, value, callback, source, options) { - const ruleType = rule.type - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value, ruleType) && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options, ruleType) - - if (!isEmptyValue(value, ruleType)) { - rules.type(rule, value, source, errors, options) - } - } - - callback(errors) -} - -/** - * Performs validation for any type. - * - * @param rule The validation rule. - * @param value The value of the field on the source object. - * @param callback The callback function. - * @param source The source object being validated. - * @param options The validation options. - * @param options.messages The validation messages. - */ - -function any(rule, value, callback, source, options) { - const errors = [] - const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) - - if (validate) { - if (isEmptyValue(value) && !rule.required) { - return callback() - } - - rules.required(rule, value, source, errors, options) - } - - callback(errors) -} - -const validators = { - string, - method, - number, - boolean: _boolean, - regexp, - integer, - float: floatFn, - array, - object, - enum: enumerable$1, - pattern: pattern$2, - date, - url: type$1, - hex: type$1, - email: type$1, - required: required$1, - any -} - -function newMessages() { - return { - default: 'Validation error on field %s', - required: '%s is required', - enum: '%s must be one of %s', - whitespace: '%s cannot be empty', - date: { - format: '%s date %s is invalid for format %s', - parse: '%s date could not be parsed, %s is invalid ', - invalid: '%s date %s is invalid' - }, - types: { - string: '%s is not a %s', - method: '%s is not a %s (function)', - array: '%s is not an %s', - object: '%s is not an %s', - number: '%s is not a %s', - date: '%s is not a %s', - boolean: '%s is not a %s', - integer: '%s is not an %s', - float: '%s is not a %s', - regexp: '%s is not a valid %s', - email: '%s is not a valid %s', - url: '%s is not a valid %s', - hex: '%s is not a valid %s' - }, - string: { - len: '%s must be exactly %s characters', - min: '%s must be at least %s characters', - max: '%s cannot be longer than %s characters', - range: '%s must be between %s and %s characters' - }, - number: { - len: '%s must equal %s', - min: '%s cannot be less than %s', - max: '%s cannot be greater than %s', - range: '%s must be between %s and %s' - }, - array: { - len: '%s must be exactly %s in length', - min: '%s cannot be less than %s in length', - max: '%s cannot be greater than %s in length', - range: '%s must be between %s and %s in length' - }, - pattern: { - mismatch: '%s value %s does not match pattern %s' - }, - clone: function clone() { - const cloned = JSON.parse(JSON.stringify(this)) - cloned.clone = this.clone - return cloned - } - } -} -const messages = newMessages() - -/** - * Encapsulates a validation schema. - * - * @param descriptor An object declaring validation rules - * for this schema. - */ - -function Schema(descriptor) { - this.rules = null - this._messages = messages - this.define(descriptor) -} - -Schema.prototype = { - messages: function messages(_messages) { - if (_messages) { - this._messages = deepMerge(newMessages(), _messages) - } - - return this._messages - }, - define: function define(rules) { - 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 = {} - let z - let item - - for (z in rules) { - if (rules.hasOwnProperty(z)) { - item = rules[z] - this.rules[z] = Array.isArray(item) ? item : [item] - } - } - }, - validate: function validate(source_, o, oc) { - const _this = this - - if (o === void 0) { - o = {} - } - - if (oc === void 0) { - oc = function oc() {} - } - - let source = source_ - let options = o - let callback = oc - - if (typeof options === 'function') { - callback = options - options = {} - } - - if (!this.rules || Object.keys(this.rules).length === 0) { - if (callback) { - callback() - } - - return Promise.resolve() - } - - function complete(results) { - let i - let errors = [] - let fields = {} - - function add(e) { - if (Array.isArray(e)) { - let _errors - - errors = (_errors = errors).concat.apply(_errors, e) - } else { - errors.push(e) - } - } - - for (i = 0; i < results.length; i++) { - add(results[i]) - } - - if (!errors.length) { - errors = null - fields = null - } else { - fields = convertFieldsError(errors) - } - - callback(errors, fields) - } - - if (options.messages) { - let messages$1 = this.messages() - - if (messages$1 === messages) { - messages$1 = newMessages() - } - - deepMerge(messages$1, options.messages) - options.messages = messages$1 - } else { - options.messages = this.messages() - } - - let arr - let value - const series = {} - const keys = options.keys || Object.keys(this.rules) - keys.forEach((z) => { - arr = _this.rules[z] - value = source[z] - arr.forEach((r) => { - let rule = r - - if (typeof rule.transform === 'function') { - if (source === source_) { - source = { ...source } - } - - value = source[z] = rule.transform(value) - } - - if (typeof rule === 'function') { - rule = { - validator: rule - } - } else { - rule = { ...rule } - } - - rule.validator = _this.getValidationMethod(rule) - rule.field = z - rule.fullField = rule.fullField || z - rule.type = _this.getType(rule) - - if (!rule.validator) { - return - } - - series[z] = series[z] || [] - series[z].push({ - rule, - value, - source, - field: z - }) - }) - }) - const errorFields = {} - return asyncMap(series, options, (data, doIt) => { - const { rule } = data - let 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 { ...schema, fullField: `${rule.fullField}.${key}` } - } - - function cb(e) { - if (e === void 0) { - e = [] - } - - let errors = e - - if (!Array.isArray(errors)) { - errors = [errors] - } - - if (!options.suppressWarning && errors.length) { - Schema.warning('async-validator:', errors) - } - - if (errors.length && rule.message) { - errors = [].concat(rule.message) - } - - errors = errors.map(complementError(rule)) - - if (options.first && errors.length) { - errorFields[rule.field] = 1 - return doIt(errors) - } - - if (!deep) { - doIt(errors) - } 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) { - errors = [].concat(rule.message).map(complementError(rule)) - } else if (options.error) { - errors = [options.error(rule, format(options.messages.required, rule.field))] - } else { - errors = [] - } - - return doIt(errors) - } - - let fieldsSchema = {} - - if (rule.defaultField) { - for (const k in data.value) { - if (data.value.hasOwnProperty(k)) { - fieldsSchema[k] = rule.defaultField - } - } - } - - fieldsSchema = { ...fieldsSchema, ...data.rule.fields } - - for (const f in fieldsSchema) { - if (fieldsSchema.hasOwnProperty(f)) { - const fieldSchema = Array.isArray(fieldsSchema[f]) ? fieldsSchema[f] : [fieldsSchema[f]] - fieldsSchema[f] = fieldSchema.map(addFullfield.bind(null, f)) - } - } - - const schema = new Schema(fieldsSchema) - 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, (errs) => { - const finalErrors = [] - - if (errors && errors.length) { - finalErrors.push.apply(finalErrors, errors) - } - - if (errs && errs.length) { - finalErrors.push.apply(finalErrors, errs) - } - - doIt(finalErrors.length ? finalErrors : null) - }) - } - } - - let res - - if (rule.asyncValidator) { - res = rule.asyncValidator(rule, data.value, cb, data.source, options) - } else if (rule.validator) { - res = rule.validator(rule, data.value, cb, data.source, options) - - if (res === true) { - cb() - } else if (res === false) { - cb(rule.message || `${rule.field} fails`) - } else if (res instanceof Array) { - cb(res) - } else if (res instanceof Error) { - cb(res.message) - } - } - - if (res && res.then) { - res.then(() => cb(), (e) => cb(e)) - } - }, (results) => { - complete(results) - }) - }, - getType: 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' - }, - getValidationMethod: function getValidationMethod(rule) { - if (typeof rule.validator === 'function') { - return rule.validator - } - - const keys = Object.keys(rule) - const 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)] || false - } -} - -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 -} - -Schema.warning = warning -Schema.messages = messages - -export default Schema -// # sourceMappingURL=index.js.map +function _extends() { + _extends = Object.assign || function (target) { + for (let i = 1; i < arguments.length; i++) { + const source = arguments[i] + + for (const key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key] + } + } + } + + return target + } + + return _extends.apply(this, arguments) +} + +/* eslint no-console:0 */ +const formatRegExp = /%[sdj%]/g +let warning = function warning() {} // don't print warning message when in production env or node runtime + +if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV !== 'production' && typeof window + !== 'undefined' && typeof document !== 'undefined') { + warning = function warning(type, errors) { + if (typeof console !== 'undefined' && console.warn) { + if (errors.every((e) => typeof e === 'string')) { + console.warn(type, errors) + } + } + } +} + +function convertFieldsError(errors) { + if (!errors || !errors.length) return null + const fields = {} + errors.forEach((error) => { + const { field } = error + fields[field] = fields[field] || [] + fields[field].push(error) + }) + return fields +} + +function format() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key] + } + + let i = 1 + const f = args[0] + const len = args.length + + if (typeof f === 'function') { + return f.apply(null, args.slice(1)) + } + + if (typeof f === 'string') { + let str = String(f).replace(formatRegExp, (x) => { + if (x === '%%') { + return '%' + } + + if (i >= len) { + return x + } + + switch (x) { + case '%s': + return String(args[i++]) + + case '%d': + return Number(args[i++]) + + case '%j': + try { + return JSON.stringify(args[i++]) + } catch (_) { + return '[Circular]' + } + + break + + default: + return x + } + }) + + for (let arg = args[i]; i < len; arg = args[++i]) { + str += ` ${arg}` + } + + return str + } + + return f +} + +function isNativeStringType(type) { + return type === 'string' || type === 'url' || type === 'hex' || type === 'email' || type === 'pattern' +} + +function isEmptyValue(value, type) { + if (value === undefined || value === null) { + return true + } + + if (type === 'array' && Array.isArray(value) && !value.length) { + return true + } + + if (isNativeStringType(type) && typeof value === 'string' && !value) { + return true + } + + return false +} + +function asyncParallelArray(arr, func, callback) { + const results = [] + let total = 0 + const arrLength = arr.length + + function count(errors) { + results.push.apply(results, errors) + total++ + + if (total === arrLength) { + callback(results) + } + } + + arr.forEach((a) => { + func(a, count) + }) +} + +function asyncSerialArray(arr, func, callback) { + let index = 0 + const arrLength = arr.length + + function next(errors) { + if (errors && errors.length) { + callback(errors) + return + } + + const original = index + index += 1 + + if (original < arrLength) { + func(arr[original], next) + } else { + callback([]) + } + } + + next([]) +} + +function flattenObjArr(objArr) { + const ret = [] + Object.keys(objArr).forEach((k) => { + ret.push.apply(ret, objArr[k]) + }) + return ret +} + +function asyncMap(objArr, option, func, callback) { + if (option.first) { + const _pending = new Promise((resolve, reject) => { + const next = function next(errors) { + callback(errors) + return errors.length ? reject({ + errors, + fields: convertFieldsError(errors) + }) : resolve() + } + + const flattenArr = flattenObjArr(objArr) + asyncSerialArray(flattenArr, func, next) + }) + + _pending.catch((e) => e) + + return _pending + } + + let firstFields = option.firstFields || [] + + if (firstFields === true) { + firstFields = Object.keys(objArr) + } + + const objArrKeys = Object.keys(objArr) + const objArrLength = objArrKeys.length + let total = 0 + const results = [] + const pending = new Promise((resolve, reject) => { + const next = function next(errors) { + results.push.apply(results, errors) + total++ + + if (total === objArrLength) { + callback(results) + return results.length ? reject({ + errors: results, + fields: convertFieldsError(results) + }) : resolve() + } + } + + if (!objArrKeys.length) { + callback(results) + resolve() + } + + objArrKeys.forEach((key) => { + const arr = objArr[key] + + if (firstFields.indexOf(key) !== -1) { + asyncSerialArray(arr, func, next) + } else { + asyncParallelArray(arr, func, next) + } + }) + }) + pending.catch((e) => e) + return pending +} + +function complementError(rule) { + return function (oe) { + if (oe && oe.message) { + oe.field = oe.field || rule.fullField + return oe + } + + return { + message: typeof oe === 'function' ? oe() : oe, + field: oe.field || rule.fullField + } + } +} + +function deepMerge(target, source) { + if (source) { + for (const s in source) { + if (source.hasOwnProperty(s)) { + const value = source[s] + + if (typeof value === 'object' && typeof target[s] === 'object') { + target[s] = { ...target[s], ...value } + } else { + target[s] = value + } + } + } + } + + return target +} + +/** + * Rule for validating required fields. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function required(rule, value, source, errors, options, type) { + if (rule.required && (!source.hasOwnProperty(rule.field) || isEmptyValue(value, type || rule.type))) { + errors.push(format(options.messages.required, rule.fullField)) + } +} + +/** + * Rule for validating whitespace. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function whitespace(rule, value, source, errors, options) { + if (/^\s+$/.test(value) || value === '') { + errors.push(format(options.messages.whitespace, rule.fullField)) + } +} + +/* eslint max-len:0 */ + +const pattern = { + // http://emailregex.com/ + email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, + url: new RegExp( + '^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$', + 'i' + ), + hex: /^#?([a-f0-9]{6}|[a-f0-9]{3})$/i +} +var types = { + integer: function integer(value) { + return /^(-)?\d+$/.test(value); + }, + float: function float(value) { + return /^(-)?\d+(\.\d+)?$/.test(value); + }, + array: function array(value) { + return Array.isArray(value) + }, + regexp: function regexp(value) { + if (value instanceof RegExp) { + return true + } + + try { + return !!new RegExp(value) + } catch (e) { + return false + } + }, + date: function date(value) { + return typeof value.getTime === 'function' && typeof value.getMonth === 'function' && typeof value.getYear + === 'function' + }, + number: function number(value) { + if (isNaN(value)) { + return false + } + + // 淇敼婧愮爜锛屽皢瀛楃涓叉暟鍊煎厛杞负鏁板�� + return typeof +value === 'number' + }, + object: function object(value) { + return typeof value === 'object' && !types.array(value) + }, + method: function method(value) { + return typeof value === 'function' + }, + email: function email(value) { + return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255 + }, + url: function url(value) { + return typeof value === 'string' && !!value.match(pattern.url) + }, + hex: function hex(value) { + return typeof value === 'string' && !!value.match(pattern.hex) + } +} +/** + * Rule for validating the type of a value. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function type(rule, value, source, errors, options) { + if (rule.required && value === undefined) { + required(rule, value, source, errors, options) + return + } + + const custom = ['integer', 'float', 'array', 'regexp', 'object', 'method', 'email', 'number', 'date', 'url', 'hex'] + const ruleType = rule.type + + if (custom.indexOf(ruleType) > -1) { + if (!types[ruleType](value)) { + errors.push(format(options.messages.types[ruleType], rule.fullField, rule.type)) + } // straight typeof check + } else if (ruleType && typeof value !== rule.type) { + errors.push(format(options.messages.types[ruleType], rule.fullField, rule.type)) + } +} + +/** + * Rule for validating minimum and maximum allowed values. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function range(rule, value, source, errors, options) { + const len = typeof rule.len === 'number' + const min = typeof rule.min === 'number' + const max = typeof rule.max === 'number' // 姝e垯鍖归厤鐮佺偣鑼冨洿浠嶶+010000涓�鐩村埌U+10FFFF鐨勬枃瀛楋紙琛ュ厖骞抽潰Supplementary Plane锛� + + const spRegexp = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g + let val = value + let key = null + const num = typeof value === 'number' + const str = typeof value === 'string' + const arr = Array.isArray(value) + + if (num) { + key = 'number' + } else if (str) { + key = 'string' + } else if (arr) { + key = 'array' + } // if the value is not of a supported type for range validation + // the validation rule rule should use the + // type property to also test for a particular type + + if (!key) { + return false + } + + if (arr) { + val = value.length + } + + if (str) { + // 澶勭悊鐮佺偣澶т簬U+010000鐨勬枃瀛條ength灞炴�т笉鍑嗙‘鐨刡ug锛屽"馉馉馉".lenght !== 3 + val = value.replace(spRegexp, '_').length + } + + if (len) { + if (val !== rule.len) { + errors.push(format(options.messages[key].len, rule.fullField, rule.len)) + } + } else if (min && !max && val < rule.min) { + errors.push(format(options.messages[key].min, rule.fullField, rule.min)) + } else if (max && !min && val > rule.max) { + errors.push(format(options.messages[key].max, rule.fullField, rule.max)) + } else if (min && max && (val < rule.min || val > rule.max)) { + errors.push(format(options.messages[key].range, rule.fullField, rule.min, rule.max)) + } +} + +const ENUM = 'enum' +/** + * Rule for validating a value exists in an enumerable list. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function enumerable(rule, value, source, errors, options) { + rule[ENUM] = Array.isArray(rule[ENUM]) ? rule[ENUM] : [] + + if (rule[ENUM].indexOf(value) === -1) { + errors.push(format(options.messages[ENUM], rule.fullField, rule[ENUM].join(', '))) + } +} + +/** + * Rule for validating a regular expression pattern. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param source The source object being validated. + * @param errors An array of errors that this rule may add + * validation errors to. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function pattern$1(rule, value, source, errors, options) { + if (rule.pattern) { + if (rule.pattern instanceof RegExp) { + // if a RegExp instance is passed, reset `lastIndex` in case its `global` + // flag is accidentally set to `true`, which in a validation scenario + // is not necessary and the result might be misleading + rule.pattern.lastIndex = 0 + + if (!rule.pattern.test(value)) { + errors.push(format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern)) + } + } else if (typeof rule.pattern === 'string') { + const _pattern = new RegExp(rule.pattern) + + if (!_pattern.test(value)) { + errors.push(format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern)) + } + } + } +} + +const rules = { + required, + whitespace, + type, + range, + enum: enumerable, + pattern: pattern$1 +} + +/** + * Performs validation for string types. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function string(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value, 'string') && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options, 'string') + + if (!isEmptyValue(value, 'string')) { + rules.type(rule, value, source, errors, options) + rules.range(rule, value, source, errors, options) + rules.pattern(rule, value, source, errors, options) + + if (rule.whitespace === true) { + rules.whitespace(rule, value, source, errors, options) + } + } + } + + callback(errors) +} + +/** + * Validates a function. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function method(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules.type(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates a number. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function number(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (value === '') { + value = undefined + } + + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules.type(rule, value, source, errors, options) + rules.range(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates a boolean. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function _boolean(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules.type(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates the regular expression type. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function regexp(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (!isEmptyValue(value)) { + rules.type(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates a number is an integer. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function integer(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules.type(rule, value, source, errors, options) + rules.range(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates a number is a floating point number. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function floatFn(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules.type(rule, value, source, errors, options) + rules.range(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates an array. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function array(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value, 'array') && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options, 'array') + + if (!isEmptyValue(value, 'array')) { + rules.type(rule, value, source, errors, options) + rules.range(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates an object. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function object(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules.type(rule, value, source, errors, options) + } + } + + callback(errors) +} + +const ENUM$1 = 'enum' +/** + * Validates an enumerable list. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function enumerable$1(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (value !== undefined) { + rules[ENUM$1](rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Validates a regular expression pattern. + * + * Performs validation when a rule only contains + * a pattern property but is not declared as a string type. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function pattern$2(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value, 'string') && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (!isEmptyValue(value, 'string')) { + rules.pattern(rule, value, source, errors, options) + } + } + + callback(errors) +} + +function date(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + + if (!isEmptyValue(value)) { + let dateObject + + if (typeof value === 'number') { + dateObject = new Date(value) + } else { + dateObject = value + } + + rules.type(rule, dateObject, source, errors, options) + + if (dateObject) { + rules.range(rule, dateObject.getTime(), source, errors, options) + } + } + } + + callback(errors) +} + +function required$1(rule, value, callback, source, options) { + const errors = [] + const type = Array.isArray(value) ? 'array' : typeof value + rules.required(rule, value, source, errors, options, type) + callback(errors) +} + +function type$1(rule, value, callback, source, options) { + const ruleType = rule.type + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value, ruleType) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options, ruleType) + + if (!isEmptyValue(value, ruleType)) { + rules.type(rule, value, source, errors, options) + } + } + + callback(errors) +} + +/** + * Performs validation for any type. + * + * @param rule The validation rule. + * @param value The value of the field on the source object. + * @param callback The callback function. + * @param source The source object being validated. + * @param options The validation options. + * @param options.messages The validation messages. + */ + +function any(rule, value, callback, source, options) { + const errors = [] + const validate = rule.required || !rule.required && source.hasOwnProperty(rule.field) + + if (validate) { + if (isEmptyValue(value) && !rule.required) { + return callback() + } + + rules.required(rule, value, source, errors, options) + } + + callback(errors) +} + +const validators = { + string, + method, + number, + boolean: _boolean, + regexp, + integer, + float: floatFn, + array, + object, + enum: enumerable$1, + pattern: pattern$2, + date, + url: type$1, + hex: type$1, + email: type$1, + required: required$1, + any +} + +function newMessages() { + return { + default: 'Validation error on field %s', + required: '%s is required', + enum: '%s must be one of %s', + whitespace: '%s cannot be empty', + date: { + format: '%s date %s is invalid for format %s', + parse: '%s date could not be parsed, %s is invalid ', + invalid: '%s date %s is invalid' + }, + types: { + string: '%s is not a %s', + method: '%s is not a %s (function)', + array: '%s is not an %s', + object: '%s is not an %s', + number: '%s is not a %s', + date: '%s is not a %s', + boolean: '%s is not a %s', + integer: '%s is not an %s', + float: '%s is not a %s', + regexp: '%s is not a valid %s', + email: '%s is not a valid %s', + url: '%s is not a valid %s', + hex: '%s is not a valid %s' + }, + string: { + len: '%s must be exactly %s characters', + min: '%s must be at least %s characters', + max: '%s cannot be longer than %s characters', + range: '%s must be between %s and %s characters' + }, + number: { + len: '%s must equal %s', + min: '%s cannot be less than %s', + max: '%s cannot be greater than %s', + range: '%s must be between %s and %s' + }, + array: { + len: '%s must be exactly %s in length', + min: '%s cannot be less than %s in length', + max: '%s cannot be greater than %s in length', + range: '%s must be between %s and %s in length' + }, + pattern: { + mismatch: '%s value %s does not match pattern %s' + }, + clone: function clone() { + const cloned = JSON.parse(JSON.stringify(this)) + cloned.clone = this.clone + return cloned + } + } +} +const messages = newMessages() + +/** + * Encapsulates a validation schema. + * + * @param descriptor An object declaring validation rules + * for this schema. + */ + +function Schema(descriptor) { + this.rules = null + this._messages = messages + this.define(descriptor) +} + +Schema.prototype = { + messages: function messages(_messages) { + if (_messages) { + this._messages = deepMerge(newMessages(), _messages) + } + + return this._messages + }, + define: function define(rules) { + 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 = {} + let z + let item + + for (z in rules) { + if (rules.hasOwnProperty(z)) { + item = rules[z] + this.rules[z] = Array.isArray(item) ? item : [item] + } + } + }, + validate: function validate(source_, o, oc) { + const _this = this + + if (o === void 0) { + o = {} + } + + if (oc === void 0) { + oc = function oc() {} + } + + let source = source_ + let options = o + let callback = oc + + if (typeof options === 'function') { + callback = options + options = {} + } + + if (!this.rules || Object.keys(this.rules).length === 0) { + if (callback) { + callback() + } + + return Promise.resolve() + } + + function complete(results) { + let i + let errors = [] + let fields = {} + + function add(e) { + if (Array.isArray(e)) { + let _errors + + errors = (_errors = errors).concat.apply(_errors, e) + } else { + errors.push(e) + } + } + + for (i = 0; i < results.length; i++) { + add(results[i]) + } + + if (!errors.length) { + errors = null + fields = null + } else { + fields = convertFieldsError(errors) + } + + callback(errors, fields) + } + + if (options.messages) { + let messages$1 = this.messages() + + if (messages$1 === messages) { + messages$1 = newMessages() + } + + deepMerge(messages$1, options.messages) + options.messages = messages$1 + } else { + options.messages = this.messages() + } + + let arr + let value + const series = {} + const keys = options.keys || Object.keys(this.rules) + keys.forEach((z) => { + arr = _this.rules[z] + value = source[z] + arr.forEach((r) => { + let rule = r + + if (typeof rule.transform === 'function') { + if (source === source_) { + source = { ...source } + } + + value = source[z] = rule.transform(value) + } + + if (typeof rule === 'function') { + rule = { + validator: rule + } + } else { + rule = { ...rule } + } + + rule.validator = _this.getValidationMethod(rule) + rule.field = z + rule.fullField = rule.fullField || z + rule.type = _this.getType(rule) + + if (!rule.validator) { + return + } + + series[z] = series[z] || [] + series[z].push({ + rule, + value, + source, + field: z + }) + }) + }) + const errorFields = {} + return asyncMap(series, options, (data, doIt) => { + const { rule } = data + let 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 { ...schema, fullField: `${rule.fullField}.${key}` } + } + + function cb(e) { + if (e === void 0) { + e = [] + } + + let errors = e + + if (!Array.isArray(errors)) { + errors = [errors] + } + + if (!options.suppressWarning && errors.length) { + Schema.warning('async-validator:', errors) + } + + if (errors.length && rule.message) { + errors = [].concat(rule.message) + } + + errors = errors.map(complementError(rule)) + + if (options.first && errors.length) { + errorFields[rule.field] = 1 + return doIt(errors) + } + + if (!deep) { + doIt(errors) + } 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) { + errors = [].concat(rule.message).map(complementError(rule)) + } else if (options.error) { + errors = [options.error(rule, format(options.messages.required, rule.field))] + } else { + errors = [] + } + + return doIt(errors) + } + + let fieldsSchema = {} + + if (rule.defaultField) { + for (const k in data.value) { + if (data.value.hasOwnProperty(k)) { + fieldsSchema[k] = rule.defaultField + } + } + } + + fieldsSchema = { ...fieldsSchema, ...data.rule.fields } + + for (const f in fieldsSchema) { + if (fieldsSchema.hasOwnProperty(f)) { + const fieldSchema = Array.isArray(fieldsSchema[f]) ? fieldsSchema[f] : [fieldsSchema[f]] + fieldsSchema[f] = fieldSchema.map(addFullfield.bind(null, f)) + } + } + + const schema = new Schema(fieldsSchema) + 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, (errs) => { + const finalErrors = [] + + if (errors && errors.length) { + finalErrors.push.apply(finalErrors, errors) + } + + if (errs && errs.length) { + finalErrors.push.apply(finalErrors, errs) + } + + doIt(finalErrors.length ? finalErrors : null) + }) + } + } + + let res + + if (rule.asyncValidator) { + res = rule.asyncValidator(rule, data.value, cb, data.source, options) + } else if (rule.validator) { + res = rule.validator(rule, data.value, cb, data.source, options) + + if (res === true) { + cb() + } else if (res === false) { + cb(rule.message || `${rule.field} fails`) + } else if (res instanceof Array) { + cb(res) + } else if (res instanceof Error) { + cb(res.message) + } + } + + if (res && res.then) { + res.then(() => cb(), (e) => cb(e)) + } + }, (results) => { + complete(results) + }) + }, + getType: 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' + }, + getValidationMethod: function getValidationMethod(rule) { + if (typeof rule.validator === 'function') { + return rule.validator + } + + const keys = Object.keys(rule) + const 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)] || false + } +} + +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 +} + +Schema.warning = warning +Schema.messages = messages + +export default Schema +// # sourceMappingURL=index.js.map -- Gitblit v1.9.3