{"version":3,"file":"validator.cjs","sources":["../../../components/form/validator.ts"],"sourcesContent":["import { isColor, isDefined, isObject, isPromise, toDate, toNumber } from '@vexip-ui/utils'\n\n// export type Trigger = 'blur' | 'change'\n\nexport type Types =\n  | 'string'\n  | 'number'\n  | 'boolean'\n  | 'int'\n  | 'float'\n  | 'array'\n  | 'object'\n  | 'date'\n  | 'url'\n  | 'color'\n  | 'email'\ntype Range = [number, number]\ntype ValidatorResult = boolean | string | Error | Promise<boolean | string | Error>\n\nexport interface Rule<T = any> {\n  // trigger?: Trigger,\n  required?: boolean,\n  type?: Types,\n  length?: number,\n  range?: Range,\n  strict?: boolean,\n  enums?: T[],\n  message?: string,\n  validator?(value: T, model: Record<string, any>): ValidatorResult\n}\n\ntype TypeOptions = Pick<Rule, 'length' | 'range' | 'strict'>\n\nconst DEFAULT_MESSAGE = 'Validate failed'\n\nconst N_100_200 = '1\\\\d\\\\d|2([0-4]\\\\d|5[0-5])'\nconst IPV4_FIRST = `[1-9](\\\\d)?|${N_100_200}`\nconst IPV4_UNIT = `\\\\d{1,2}|${N_100_200}`\nconst IPV4_REG = `(?:${IPV4_FIRST})\\\\.(?:${IPV4_UNIT})\\\\.(?:${IPV4_UNIT})\\\\.(?:${IPV4_UNIT})`\n\nconst HOST_REG = '(?:[a-zA-Z0-9][\\\\w-]*\\\\.)?(?:[a-zA-Z0-9][\\\\w-]*)(?:\\\\.[a-zA-Z]+){1,2}'\nconst PARAM_REG =\n  '(?:(?:[\\\\/]+[^\\\\?\\\\.]+)+)?(?:[\\\\/]*)?(\\\\?([^&\\\\.]+=[^&\\\\.]*)(&[^&\\\\.]+=[^&\\\\.]*)*)?(#.*)?'\nconst URL_REG = new RegExp(\n  `^(?:[a-z]{2,5}:(\\\\/+)?)?\\\\/\\\\/((?:${IPV4_REG})|(?:${HOST_REG}))(?:${PARAM_REG})?$`,\n)\n\nconst EMAIL_REG = /^(?:[a-zA-Z0-9][\\w-]*)@(?:[a-zA-Z0-9][\\w-]*)(?:\\.[a-zA-Z]+){1,2}$/\n\nconst TYPE_LIST = new Set([\n  'string',\n  'number',\n  'boolean',\n  'int',\n  'float',\n  'array',\n  'object',\n  'date',\n  'url',\n  'color',\n  'email',\n] as Types[])\n\nexport async function validate(\n  rules: Rule | Rule[],\n  value: unknown,\n  model: Record<string, unknown>,\n  validateAll = true,\n  defaultMsg = DEFAULT_MESSAGE,\n) {\n  if (!Array.isArray(rules)) {\n    rules = [rules]\n  }\n\n  const errors: string[] = []\n\n  for (const rule of rules as Rule[]) {\n    const { message = defaultMsg, validator } = rule\n\n    if (typeof validator === 'function') {\n      let result\n\n      try {\n        result = validator(value, model)\n\n        if (isPromise(result)) {\n          result = await result\n        }\n      } catch (error) {\n        result = error instanceof Error ? error.message : error\n      }\n\n      if (result !== true) {\n        const errorMessage = typeof result === 'string' ? result : message\n\n        errors.push(errorMessage)\n\n        if (!validateAll) break\n      }\n    }\n\n    if (rule.required && !validateRequirement(value)) {\n      errors.push(message)\n\n      if (!validateAll) break\n    }\n\n    if (isDefined(value) && value !== '') {\n      if (rule.enums && !validateEnumeration(value, rule.enums)) {\n        errors.push(message)\n\n        if (!validateAll) break\n      }\n\n      if (rule.type && !validateType(value, rule.type, rule)) {\n        errors.push(message)\n\n        if (!validateAll) break\n      }\n    }\n  }\n\n  return errors\n}\n\nexport function validateRequirement(value: any) {\n  return !(\n    !isDefined(value) ||\n    value.toString().trim() === '' ||\n    (Array.isArray(value) && !value.length) ||\n    (isObject(value) && !Object.keys(value).length)\n  )\n}\n\nexport function validateEnumeration<T>(value: T | T[], options: T[]) {\n  if (!Array.isArray(options) || !options.length) return true\n\n  if (Array.isArray(value)) {\n    const enumSet = new Set(options)\n\n    for (const item of value) {\n      if (!enumSet.has(item)) {\n        return false\n      }\n    }\n\n    return true\n  } else {\n    return options.includes(value)\n  }\n}\n\nexport function validateType(value: unknown, type: Types, options: TypeOptions = {}) {\n  if (!TYPE_LIST.has(type)) return true\n\n  switch (type) {\n    case 'string':\n      return validateString(value, options.length, options.range)\n    case 'number':\n      return validateNumber(value, options.strict, options.length, options.range)\n    case 'boolean':\n      return validateBoolean(value, options.strict)\n    case 'int':\n      return validateInt(value, options.strict, options.length, options.range)\n    case 'float':\n      return validateFloat(value, options.strict, options.length, options.range)\n    case 'array':\n      return Array.isArray(value)\n    case 'object':\n      return isObject(value)\n    case 'date':\n      return validateDate(value, options.strict)\n    case 'url':\n      return validateUrl(value)\n    case 'color':\n      return typeof value === 'string' && isColor(value)\n    case 'email':\n      return validateEmail(value)\n  }\n}\n\nexport function validateString(value: unknown, length?: number, range?: Range) {\n  if (typeof value !== 'string') return false\n\n  if (isDefined(length) && value.length !== length) {\n    return false\n  }\n\n  if (Array.isArray(range)) {\n    const [min, max] = range\n\n    if (min && value.length < min) return false\n\n    if (max && value.length > max) return false\n  }\n\n  return true\n}\n\nexport function validateNumber(value: unknown, strict?: boolean, length?: number, range?: Range) {\n  if (strict) {\n    if (typeof value !== 'number') return false\n  } else {\n    value = Number(value)\n\n    if (Number.isNaN(value)) return false\n  }\n\n  const number = value as number\n\n  if (isDefined(length) && number.toString().length !== length) {\n    return false\n  }\n\n  if (Array.isArray(range)) {\n    const [min, max] = range\n\n    if (isDefined(min) && number < min) return false\n\n    if (isDefined(max) && number > max) return false\n  }\n\n  return true\n}\n\nexport function validateBoolean(value: unknown, strict?: boolean) {\n  if (!strict) {\n    if (typeof value === 'string') {\n      return value === 'true' || value === 'false'\n    }\n\n    if (typeof value === 'number') {\n      return value === 1 || value === 0\n    }\n  }\n\n  return typeof value === 'boolean'\n}\n\nexport function validateInt(value: unknown, strict?: boolean, length?: number, range?: Range) {\n  if (validateNumber(value, strict, length, range)) {\n    const number = toNumber(value as any)\n\n    return Math.ceil(number) === number\n  }\n\n  return false\n}\n\nexport function validateFloat(value: unknown, strict?: boolean, length?: number, range?: Range) {\n  if (validateNumber(value, strict, length, range)) {\n    const number = toNumber(value as any)\n\n    return strict ? Math.ceil(number) !== number : number.toString().includes('.')\n  }\n\n  return false\n}\n\nexport function validateDate(value: unknown, strict?: boolean) {\n  if (strict && !(value instanceof Date)) {\n    return false\n  }\n\n  try {\n    toDate(value as any)\n  } catch (e) {\n    return false\n  }\n\n  return true\n}\n\nexport function validateUrl(value: unknown) {\n  return typeof value === 'string' && URL_REG.test(value)\n}\n\nexport function validateEmail(value: unknown) {\n  return typeof value === 'string' && EMAIL_REG.test(value)\n}\n"],"names":["DEFAULT_MESSAGE","N_100_200","IPV4_FIRST","IPV4_UNIT","IPV4_REG","HOST_REG","PARAM_REG","URL_REG","EMAIL_REG","TYPE_LIST","validate","rules","value","model","validateAll","defaultMsg","errors","rule","message","validator","result","isPromise","error","errorMessage","validateRequirement","isDefined","validateEnumeration","validateType","isObject","options","enumSet","item","type","validateString","validateNumber","validateBoolean","validateInt","validateFloat","validateDate","validateUrl","isColor","validateEmail","length","range","min","max","strict","number","toNumber","toDate"],"mappings":"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"}