UNPKG

vexip-ui

Version:

A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good

1 lines 11.6 kB
{"version":3,"file":"validator.mjs","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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"}