qa-regulatory-gwj-app/uni_modules/uview-ui/libs/util/async-validator.js

1344 lines
38 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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' // 正则匹配码点范围从U+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的文字length属性不准确的bug如"𠮷𠮷𠮷".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