think_validtion
Version:
Validtion Util for Koatty and ThinkORM.
409 lines • 13.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkParams = exports.platenumber = exports.zipcode = exports.mobile = exports.idnumber = exports.cnname = exports.plainToClass = exports.checkParamsType = exports.convertParamsType = exports.getOriginMetadata = exports.defineNewProperty = exports.recursiveGetMetadata = exports.paramterTypes = exports.ENABLE_VALIDATED = exports.PARAM_CHECK_KEY = exports.PARAM_RULE_KEY = exports.PARAM_TYPE_KEY = void 0;
const tslib_1 = require("tslib");
/**
* @ author: richen
* @ copyright: Copyright (c) - <richenlin(at)gmail.com>
* @ license: MIT
* @ version: 2020-03-20 11:34:38
*/
// tslint:disable-next-line: no-import-side-effect
require("reflect-metadata");
const think_lib_1 = tslib_1.__importDefault(require("think_lib"));
const think_logger_1 = tslib_1.__importDefault(require("think_logger"));
const think_container_1 = require("think_container");
const util_1 = require("./util");
exports.PARAM_TYPE_KEY = 'PARAM_TYPE_KEY';
exports.PARAM_RULE_KEY = 'PARAM_RULE_KEY';
exports.PARAM_CHECK_KEY = 'PARAM_CHECK_KEY';
exports.ENABLE_VALIDATED = "ENABLE_VALIDATED";
exports.paramterTypes = {
"Number": 1, "number": 1, "String": 1,
"string": 1, "Boolean": 1, "boolean": 1,
"Array": 1, "array": 1, "Tuple": 1, "tuple": 1,
"Object": 1, "object": 1, "Enum": 1, "enum": 1
};
const functionPrototype = Object.getPrototypeOf(Function);
// get property of an object
// https://tc39.github.io/ecma262/#sec-ordinarygetprototypeof
function ordinaryGetPrototypeOf(obj) {
const proto = Object.getPrototypeOf(obj);
if (typeof obj !== "function" || obj === functionPrototype) {
return proto;
}
// TypeScript doesn't set __proto__ in ES5, as it's non-standard.
// Try to determine the superclass constructor. Compatible implementations
// must either set __proto__ on a subclass constructor to the superclass constructor,
// or ensure each class has a valid `constructor` property on its prototype that
// points back to the constructor.
// If this is not the same as Function.[[Prototype]], then this is definately inherited.
// This is the case when in ES6 or when using __proto__ in a compatible browser.
if (proto !== functionPrototype) {
return proto;
}
// If the super prototype is Object.prototype, null, or undefined, then we cannot determine the heritage.
const prototype = obj.prototype;
const prototypeProto = prototype && Object.getPrototypeOf(prototype);
// tslint:disable-next-line: triple-equals
if (prototypeProto == undefined || prototypeProto === Object.prototype) {
return proto;
}
// If the constructor was not a function, then we cannot determine the heritage.
const constructor = prototypeProto.constructor;
if (typeof constructor !== "function") {
return proto;
}
// If we have some kind of self-reference, then we cannot determine the heritage.
if (constructor === obj) {
return proto;
}
// we have a pretty good guess at the heritage.
return constructor;
}
/**
* get property matadata data
*
* @param {(string | symbol)} decoratorNameKey
* @param {*} target
* @returns
*/
function listPropertyData(decoratorNameKey, target, propertyKey) {
const originMap = getOriginMetadata(decoratorNameKey, target, propertyKey);
const datas = {};
for (const [key, value] of originMap) {
datas[key] = value;
}
return datas;
}
/**
* get metadata value of a metadata key on the prototype chain of an object and property
* @param metadataKey metadata's key
* @param target the target of metadataKey
*/
function recursiveGetMetadata(metadataKey, target, propertyKey) {
// get metadata value of a metadata key on the prototype
// let metadata = Reflect.getOwnMetadata(metadataKey, target, propertyKey);
const metadata = listPropertyData(metadataKey, target, propertyKey) || {};
// get metadata value of a metadata key on the prototype chain
let parent = ordinaryGetPrototypeOf(target);
while (parent !== null) {
// metadata = Reflect.getOwnMetadata(metadataKey, parent, propertyKey);
const pmetadata = listPropertyData(metadataKey, parent, propertyKey);
if (pmetadata) {
for (const n in pmetadata) {
if (!metadata.hasOwnProperty(n)) {
metadata[n] = pmetadata[n];
}
}
}
parent = ordinaryGetPrototypeOf(parent);
}
return metadata;
}
exports.recursiveGetMetadata = recursiveGetMetadata;
/**
* Dynamically add methods for target class types
*
* @param {Function} clazz
* @param {string} protoName
* @param {Function} func
*/
function defineNewProperty(clazz, protoName, func) {
const oldMethod = Reflect.get(clazz.prototype, protoName);
if (oldMethod) {
Reflect.defineProperty(clazz.prototype, protoName, {
writable: true,
value: function fn(...props) {
// process paramter
props = func(props);
// tslint:disable-next-line: no-invalid-this
return Reflect.apply(oldMethod, this, props);
}
});
}
}
exports.defineNewProperty = defineNewProperty;
/**
*
*
* @param {(string | symbol)} metadataKey
* @param {*} target
* @param {(string | symbol)} [propertyKey]
* @returns
*/
function getOriginMetadata(metadataKey, target, propertyKey) {
// filter Object.create(null)
if (typeof target === "object" && target.constructor) {
target = target.constructor;
}
if (propertyKey) {
// for property or method
if (!Reflect.hasMetadata(metadataKey, target, propertyKey)) {
Reflect.defineMetadata(metadataKey, new Map(), target, propertyKey);
}
return Reflect.getMetadata(metadataKey, target, propertyKey);
}
else {
// for class
if (!Reflect.hasMetadata(metadataKey, target)) {
Reflect.defineMetadata(metadataKey, new Map(), target);
}
return Reflect.getMetadata(metadataKey, target);
}
}
exports.getOriginMetadata = getOriginMetadata;
/**
* Convert paramer's type to defined.
*
* @param {*} param
* @param {string} type
* @returns
*/
exports.convertParamsType = (param, type) => {
switch (type) {
case "Number":
case "number":
if (think_lib_1.default.isNaN(param)) {
return NaN;
}
if (think_lib_1.default.isNumberString(param)) {
return think_lib_1.default.toNumber(param);
}
if (think_lib_1.default.isNumber(param)) {
return param;
}
return NaN;
case "Boolean":
case "boolean":
return !!param;
case "Array":
case "array":
case "Tuple":
case "tuple":
if (think_lib_1.default.isArray(param)) {
return param;
}
return think_lib_1.default.toArray(param);
case "String":
case "string":
if (think_lib_1.default.isString(param)) {
return param;
}
return think_lib_1.default.toString(param);
// case "object":
// case "enum":
default: //any
return param;
}
};
/**
* Check the base types.
*
* @param {*} value
* @param {string} type
* @returns {*}
*/
exports.checkParamsType = function (value, type) {
switch (type) {
case "Number":
case "number":
if (!think_lib_1.default.isNumber(value) || think_lib_1.default.isNaN(value)) {
return false;
}
return true;
case "Boolean":
case "boolean":
if (!think_lib_1.default.isBoolean(value)) {
return false;
}
return true;
case "Array":
case "array":
case "Tuple":
if (!think_lib_1.default.isArray(value)) {
return false;
}
return true;
case "String":
case "string":
if (!think_lib_1.default.isString(value)) {
return false;
}
return true;
case "Object":
case "object":
case "Enum":
if (think_lib_1.default.isUndefined(value)) {
return false;
}
return true;
default: //any
return true;
}
};
/**
*
*
* @export
* @param {*} clazz
* @param {*} data
* @param {boolean} [convert=false]
* @returns
*/
function plainToClass(clazz, data, convert = false) {
try {
if (think_lib_1.default.isClass(clazz)) {
let cls;
if (data instanceof clazz) {
cls = data;
}
else {
if (!think_lib_1.default.isObject(data)) {
data = {};
}
cls = Reflect.construct(clazz, []);
}
const originMap = getOriginMetadata(exports.PARAM_TYPE_KEY, clazz);
for (const [key, value] of originMap) {
if (key && Object.prototype.hasOwnProperty.call(data, key)) {
if (convert) {
cls[key] = exports.convertParamsType(data[key], value);
}
else {
cls[key] = data[key];
if (!exports.checkParamsType(cls[key], value)) {
const err = new Error(`TypeError: invalid arguments '${key}'.`);
err.code = 400;
err.status = 400;
throw err;
}
}
}
}
return cls;
}
return data;
}
catch (err) {
think_logger_1.default.error(err);
return data;
}
}
exports.plainToClass = plainToClass;
/**
* Checks if value is a chinese name.
*
* @param {string} value
* @returns {boolean}
*/
function cnname(value) {
const reg = /^([a-zA-Z0-9\u4e00-\u9fa5\·]{1,10})$/;
return reg.test(value);
}
exports.cnname = cnname;
/**
* Checks if value is a idcard number.
*
* @param {string} value
* @returns
*/
function idnumber(value) {
if (/^\d{15}$/.test(value)) {
return true;
}
if ((/^\d{17}[0-9X]$/).test(value)) {
const vs = '1,0,x,9,8,7,6,5,4,3,2'.split(',');
const ps = '7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2'.split(',');
const ss = value.toLowerCase().split('');
let r = 0;
for (let i = 0; i < 17; i++) {
r += ps[i] * ss[i];
}
const isOk = (vs[r % 11] === ss[17]);
return isOk;
}
return false;
}
exports.idnumber = idnumber;
/**
* Checks if value is a mobile phone number.
*
* @param {string} value
* @returns {boolean}
*/
function mobile(value) {
const reg = /^(13|14|15|16|17|18|19)\d{9}$/;
return reg.test(value);
}
exports.mobile = mobile;
/**
* Checks if value is a zipcode.
*
* @param {string} value
* @returns {boolean}
*/
function zipcode(value) {
const reg = /^\d{6}$/;
return reg.test(value);
}
exports.zipcode = zipcode;
/**
* Checks if value is a platenumber.
*
* @param {string} value
* @returns {boolean}
*/
function platenumber(value) {
// let reg = new RegExp('^(([\u4e00-\u9fa5][a-zA-Z]|[\u4e00-\u9fa5]{2}\d{2}|[\u4e00-\u9fa5]{2}[a-zA-Z])[-]?|([wW][Jj][\u4e00-\u9fa5]{1}[-]?)|([a-zA-Z]{2}))([A-Za-z0-9]{5}|[DdFf][A-HJ-NP-Za-hj-np-z0-9][0-9]{4}|[0-9]{5}[DdFf])$');
// let xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/;
const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/;
// let creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/;
const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/;
if (value.length === 7) {
return creg.test(value);
}
else {
//新能源车牌
return xreg.test(value);
}
}
exports.platenumber = platenumber;
/**
* Check parameters against predefined rules
*
* @export
* @param {*} param
* @param {number} index
* @param {ParamOptions} [paramOptions={
* validRules: [],
* dtoCheck: false
* }]
*/
async function checkParams(value, paramOptions) {
if (paramOptions.isDto) {
// DTO class
const clazz = think_container_1.IOCContainer.getClass(paramOptions.type, "COMPONENT");
if (clazz) {
if (paramOptions.dtoCheck) {
value = await util_1.ClassValidator.valid(clazz, value, true);
}
else {
value = plainToClass(clazz, value, true);
}
}
}
else {
value = exports.convertParamsType(value, paramOptions.type);
//@Valid()
if (paramOptions.validRules[paramOptions.index]) {
const { type, rule, message } = paramOptions.validRules[paramOptions.index];
if (type && rule) {
util_1.ValidatorFuncs(`${paramOptions.index}`, value, type, rule, message, false);
}
}
}
return value;
}
exports.checkParams = checkParams;
//# sourceMappingURL=lib.js.map