koatty_validation 1.0.12 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,1219 @@
1
+ /*!
2
+ * @Author: richen
3
+ * @Date: 2022-02-16 18:31:49
4
+ * @License: BSD (3-Clause)
5
+ * @Copyright (c) - <richenlin(at)gmail.com>
6
+ * @HomePage: https://koatty.org/
7
+ */
8
+ import * as helper from 'koatty_lib';
9
+ import 'reflect-metadata';
10
+ import { getOriginMetadata, IOCContainer } from 'koatty_container';
11
+ import { validate, equals, notEquals, contains, isIn, isNotIn, length, isEmail, isIP, isPhoneNumber, isURL, isHash, registerDecorator, isDate } from 'class-validator';
12
+
13
+ /**
14
+ * @ author: richen
15
+ * @ copyright: Copyright (c) - <richenlin(at)gmail.com>
16
+ * @ license: MIT
17
+ * @ version: 2020-03-20 11:34:38
18
+ */
19
+ /**
20
+ * Set property as included in the process of transformation.
21
+ *
22
+ * @export
23
+ * @param {Object} object
24
+ * @param {(string | symbol)} propertyName
25
+ */
26
+ function setExpose(object, propertyName) {
27
+ const types = Reflect.getMetadata("design:type", object, propertyName);
28
+ if (types) {
29
+ const originMap = getOriginMetadata(PARAM_TYPE_KEY, object);
30
+ originMap.set(propertyName, types.name);
31
+ }
32
+ }
33
+ /**
34
+ *
35
+ *
36
+ * @export
37
+ * @param {*} clazz
38
+ * @param {*} data
39
+ * @param {boolean} [convert=false]
40
+ * @returns
41
+ */
42
+ function plainToClass(clazz, data, convert = false) {
43
+ if (helper.isClass(clazz)) {
44
+ let cls;
45
+ if (!helper.isObject(data)) {
46
+ data = {};
47
+ }
48
+ if (data instanceof clazz) {
49
+ cls = data;
50
+ }
51
+ else {
52
+ cls = Reflect.construct(clazz, []);
53
+ }
54
+ if (convert) {
55
+ return convertDtoParamsType(clazz, cls, data);
56
+ }
57
+ return Object.assign(cls, data);
58
+ }
59
+ return data;
60
+ }
61
+ /**
62
+ * convertDtoParamsType
63
+ *
64
+ * @param {*} clazz
65
+ * @param {*} cls
66
+ * @param {*} data
67
+ * @returns {*}
68
+ */
69
+ function convertDtoParamsType(clazz, cls, data) {
70
+ if (Object.prototype.hasOwnProperty.call(cls, "_typeDef")) {
71
+ for (const key in cls) {
72
+ if (Object.prototype.hasOwnProperty.call(data, key)
73
+ && Object.prototype.hasOwnProperty.call(cls._typeDef, key)) {
74
+ data[key] = convertParamsType(data[key], cls._typeDef[key]);
75
+ }
76
+ }
77
+ }
78
+ else {
79
+ const originMap = getOriginMetadata(PARAM_TYPE_KEY, clazz);
80
+ for (const [key, type] of originMap) {
81
+ if (key && Object.prototype.hasOwnProperty.call(data, key)) {
82
+ cls[key] = convertParamsType(data[key], type);
83
+ }
84
+ }
85
+ }
86
+ return cls;
87
+ }
88
+ /**
89
+ * 绑定参数类型转换
90
+ *
91
+ * @param {*} param
92
+ * @param {string} type
93
+ * @returns {*}
94
+ */
95
+ function convertParamsType(param, type) {
96
+ try {
97
+ switch (type) {
98
+ case "Number":
99
+ case "number":
100
+ if (helper.isNaN(param)) {
101
+ return NaN;
102
+ }
103
+ if (helper.isNumber(param)) {
104
+ return param;
105
+ }
106
+ if (helper.isNumberString(param)) {
107
+ return helper.toNumber(param);
108
+ }
109
+ return NaN;
110
+ case "Boolean":
111
+ case "boolean":
112
+ return !!param;
113
+ case "Array":
114
+ case "array":
115
+ case "Tuple":
116
+ case "tuple":
117
+ if (helper.isArray(param)) {
118
+ return param;
119
+ }
120
+ return helper.toArray(param);
121
+ case "String":
122
+ case "string":
123
+ if (helper.isString(param)) {
124
+ return param;
125
+ }
126
+ return helper.toString(param);
127
+ case "Null":
128
+ case "null":
129
+ return null;
130
+ case "Undefined":
131
+ case "undefined":
132
+ return undefined;
133
+ case "Bigint":
134
+ case "bigint":
135
+ if (typeof param === 'bigint') {
136
+ return param;
137
+ }
138
+ return BigInt(param);
139
+ // case "object":
140
+ // case "enum":
141
+ default: //any
142
+ return param;
143
+ }
144
+ }
145
+ catch (err) {
146
+ return param;
147
+ }
148
+ }
149
+ /**
150
+ * Check the base types.
151
+ *
152
+ * @param {*} value
153
+ * @param {string} type
154
+ * @returns {*}
155
+ */
156
+ function checkParamsType(value, type) {
157
+ switch (type) {
158
+ case "Number":
159
+ case "number":
160
+ if (!helper.isNumber(value) || helper.isNaN(value)) {
161
+ return false;
162
+ }
163
+ return true;
164
+ case "Boolean":
165
+ case "boolean":
166
+ if (!helper.isBoolean(value)) {
167
+ return false;
168
+ }
169
+ return true;
170
+ case "Array":
171
+ case "array":
172
+ case "Tuple":
173
+ case "tuple":
174
+ if (!helper.isArray(value)) {
175
+ return false;
176
+ }
177
+ return true;
178
+ case "String":
179
+ case "string":
180
+ if (!helper.isString(value)) {
181
+ return false;
182
+ }
183
+ return true;
184
+ case "Object":
185
+ case "object":
186
+ case "Enum":
187
+ case "enum":
188
+ if (helper.isTrueEmpty(value)) {
189
+ return false;
190
+ }
191
+ return true;
192
+ case "Null":
193
+ case "null":
194
+ if (!helper.isNull(value)) {
195
+ return false;
196
+ }
197
+ return true;
198
+ case "Undefined":
199
+ case "undefined":
200
+ if (!helper.isUndefined(value)) {
201
+ return false;
202
+ }
203
+ return true;
204
+ case "Bigint":
205
+ case "bigint":
206
+ if (typeof value !== 'bigint') {
207
+ return false;
208
+ }
209
+ return true;
210
+ default: //any
211
+ return true;
212
+ }
213
+ }
214
+ /**
215
+ * Checks if value is a chinese name.
216
+ *
217
+ * @param {string} value
218
+ * @returns {boolean}
219
+ */
220
+ function cnName(value) {
221
+ const reg = /^([a-zA-Z0-9\u4e00-\u9fa5\·]{1,10})$/;
222
+ return reg.test(value);
223
+ }
224
+ /**
225
+ * Checks if value is a idCard number.
226
+ *
227
+ * @param {string} value
228
+ * @returns
229
+ */
230
+ function idNumber(value) {
231
+ if (/^\d{15}$/.test(value)) {
232
+ return true;
233
+ }
234
+ if ((/^\d{17}[0-9X]$/).test(value)) {
235
+ const vs = '1,0,x,9,8,7,6,5,4,3,2'.split(',');
236
+ const ps = '7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2'.split(',');
237
+ const ss = value.toLowerCase().split('');
238
+ let r = 0;
239
+ for (let i = 0; i < 17; i++) {
240
+ r += ps[i] * ss[i];
241
+ }
242
+ const isOk = (vs[r % 11] === ss[17]);
243
+ return isOk;
244
+ }
245
+ return false;
246
+ }
247
+ /**
248
+ * Checks if value is a mobile phone number.
249
+ *
250
+ * @param {string} value
251
+ * @returns {boolean}
252
+ */
253
+ function mobile(value) {
254
+ const reg = /^(13|14|15|16|17|18|19)\d{9}$/;
255
+ return reg.test(value);
256
+ }
257
+ /**
258
+ * Checks if value is a zipCode.
259
+ *
260
+ * @param {string} value
261
+ * @returns {boolean}
262
+ */
263
+ function zipCode(value) {
264
+ const reg = /^\d{6}$/;
265
+ return reg.test(value);
266
+ }
267
+ /**
268
+ * Checks if value is a plateNumber.
269
+ *
270
+ * @param {string} value
271
+ * @returns {boolean}
272
+ */
273
+ function plateNumber(value) {
274
+ // 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])$');
275
+ // let xReg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/;
276
+ const xReg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/;
277
+ // let cReg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/;
278
+ const cReg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/;
279
+ if (value.length === 7) {
280
+ return cReg.test(value);
281
+ }
282
+ else {
283
+ //新能源车牌
284
+ return xReg.test(value);
285
+ }
286
+ }
287
+
288
+ /*
289
+ * @Description:
290
+ * @Usage:
291
+ * @Author: richen
292
+ * @Date: 2021-11-25 10:47:04
293
+ * @LastEditTime: 2021-11-25 11:07:02
294
+ */
295
+ // constant
296
+ const PARAM_TYPE_KEY = 'PARAM_TYPE_KEY';
297
+ const PARAM_RULE_KEY = 'PARAM_RULE_KEY';
298
+ const PARAM_CHECK_KEY = 'PARAM_CHECK_KEY';
299
+ const ENABLE_VALIDATED = "ENABLE_VALIDATED";
300
+ /**
301
+ * paramterTypes
302
+ *
303
+ * @export
304
+ * @enum {number}
305
+ */
306
+ var paramterTypes;
307
+ (function (paramterTypes) {
308
+ paramterTypes[paramterTypes["Number"] = 0] = "Number";
309
+ paramterTypes[paramterTypes["number"] = 1] = "number";
310
+ paramterTypes[paramterTypes["String"] = 2] = "String";
311
+ paramterTypes[paramterTypes["string"] = 3] = "string";
312
+ paramterTypes[paramterTypes["Boolean"] = 4] = "Boolean";
313
+ paramterTypes[paramterTypes["boolean"] = 5] = "boolean";
314
+ paramterTypes[paramterTypes["Array"] = 6] = "Array";
315
+ paramterTypes[paramterTypes["array"] = 7] = "array";
316
+ paramterTypes[paramterTypes["Tuple"] = 8] = "Tuple";
317
+ paramterTypes[paramterTypes["tuple"] = 9] = "tuple";
318
+ paramterTypes[paramterTypes["Object"] = 10] = "Object";
319
+ paramterTypes[paramterTypes["object"] = 11] = "object";
320
+ paramterTypes[paramterTypes["Enum"] = 12] = "Enum";
321
+ paramterTypes[paramterTypes["enum"] = 13] = "enum";
322
+ paramterTypes[paramterTypes["Bigint"] = 14] = "Bigint";
323
+ paramterTypes[paramterTypes["bigint"] = 15] = "bigint";
324
+ paramterTypes[paramterTypes["Null"] = 16] = "Null";
325
+ paramterTypes[paramterTypes["null"] = 17] = "null";
326
+ paramterTypes[paramterTypes["Undefined"] = 18] = "Undefined";
327
+ paramterTypes[paramterTypes["undefined"] = 19] = "undefined";
328
+ })(paramterTypes || (paramterTypes = {}));
329
+ class ValidateClass {
330
+ constructor() {
331
+ }
332
+ /**
333
+ *
334
+ *
335
+ * @static
336
+ * @returns
337
+ * @memberof ValidateUtil
338
+ */
339
+ static getInstance() {
340
+ return this.instance || (this.instance = new ValidateClass());
341
+ }
342
+ /**
343
+ * validated data vs dto class
344
+ *
345
+ * @param {*} Clazz
346
+ * @param {*} data
347
+ * @param {boolean} [convert=false] auto convert parameters type
348
+ * @returns {Promise<any>}
349
+ * @memberof ValidateClass
350
+ */
351
+ async valid(Clazz, data, convert = false) {
352
+ let obj = {};
353
+ if (data instanceof Clazz) {
354
+ obj = data;
355
+ }
356
+ else {
357
+ obj = plainToClass(Clazz, data, convert);
358
+ }
359
+ let errors = [];
360
+ if (convert) {
361
+ errors = await validate(obj);
362
+ }
363
+ else {
364
+ errors = await validate(obj, { skipMissingProperties: true });
365
+ }
366
+ if (errors.length > 0) {
367
+ const err = new Error(Object.values(errors[0].constraints)[0]);
368
+ err.code = 400;
369
+ err.status = 400;
370
+ throw err;
371
+ }
372
+ return obj;
373
+ }
374
+ }
375
+ /**
376
+ * ClassValidator for manual
377
+ */
378
+ const ClassValidator = ValidateClass.getInstance();
379
+ /**
380
+ * Validator Functions
381
+ */
382
+ const FunctionValidator = {
383
+ /**
384
+ * Checks if value matches ("===") the comparison.
385
+ */
386
+ Equals: (value, comparison) => {
387
+ return equals(value, comparison);
388
+ },
389
+ /**
390
+ * Checks if value does not match ("!==") the comparison.
391
+ */
392
+ NotEquals: (value, comparison) => {
393
+ return notEquals(value, comparison);
394
+ },
395
+ /**
396
+ * Checks if the string contains the seed. If given value is not a string, then it returns false.
397
+ */
398
+ Contains: (value, seed) => {
399
+ return contains(value, seed);
400
+ },
401
+ /**
402
+ * Checks if given value is in a array of allowed values.
403
+ */
404
+ IsIn: (value, possibleValues) => {
405
+ return isIn(value, possibleValues);
406
+ },
407
+ /**
408
+ * Checks if given value not in a array of allowed values.
409
+ */
410
+ IsNotIn: (value, possibleValues) => {
411
+ return isNotIn(value, possibleValues);
412
+ },
413
+ /**
414
+ * Checks if a given value is a real date.
415
+ */
416
+ IsDate: (value) => {
417
+ return helper.isDate(value);
418
+ },
419
+ /**
420
+ * Checks if the first number is greater than or equal to the second.
421
+ */
422
+ Min: (num, min) => {
423
+ return helper.toNumber(num) >= min;
424
+ },
425
+ /**
426
+ * Checks if the first number is less than or equal to the second.
427
+ */
428
+ Max: (num, max) => {
429
+ return helper.toNumber(num) <= max;
430
+ },
431
+ /**
432
+ * Checks if the string's length falls in a range. Note: this function takes into account surrogate pairs.
433
+ * If given value is not a string, then it returns false.
434
+ */
435
+ Length: (value, min, max) => {
436
+ return length(value, min, max);
437
+ },
438
+ /**
439
+ * Checks if the string is an email. If given value is not a string, then it returns false.
440
+ */
441
+ IsEmail: (value, options) => {
442
+ return isEmail(value, options);
443
+ },
444
+ /**
445
+ * Checks if the string is an IP (version 4 or 6). If given value is not a string, then it returns false.
446
+ */
447
+ IsIP: (value, version) => {
448
+ return isIP(value, version);
449
+ },
450
+ /**
451
+ * Checks if the string is a valid phone number.
452
+ * @param value — the potential phone number string to test
453
+ * @param region 2 characters uppercase country code (e.g. DE, US, CH). If users must enter the intl.
454
+ * prefix (e.g. +41), then you may pass "ZZ" or null as region.
455
+ * See [google-libphonenumber, metadata.js:countryCodeToRegionCodeMap on github]
456
+ * {@link https://github.com/ruimarinho/google-libphonenumber/blob/1e46138878cff479aafe2ce62175c6c49cb58720/src/metadata.js#L33}
457
+ */
458
+ IsPhoneNumber: (value, region) => {
459
+ return isPhoneNumber(value, region);
460
+ },
461
+ /**
462
+ * Checks if the string is an url. If given value is not a string, then it returns false.
463
+ */
464
+ IsUrl: (value, options) => {
465
+ return isURL(value, options);
466
+ },
467
+ /**
468
+ * check if the string is a hash of type algorithm. Algorithm is one of
469
+ * ['md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', 'tiger160', 'tiger192', 'crc32', 'crc32b']
470
+ */
471
+ IsHash: (value, algorithm) => {
472
+ return isHash(value, algorithm);
473
+ },
474
+ /**
475
+ * Checks if value is a chinese name.
476
+ */
477
+ IsCnName: (value) => {
478
+ if (!helper.isString(value)) {
479
+ return false;
480
+ }
481
+ return cnName(value);
482
+ },
483
+ /**
484
+ * Checks if value is a idcard number.
485
+ */
486
+ IsIdNumber: (value) => {
487
+ if (!helper.isString(value)) {
488
+ return false;
489
+ }
490
+ return idNumber(value);
491
+ },
492
+ /**
493
+ * Checks if value is a zipCode.
494
+ */
495
+ IsZipCode: (value) => {
496
+ if (!helper.isString(value)) {
497
+ return false;
498
+ }
499
+ return zipCode(value);
500
+ },
501
+ /**
502
+ * Checks if value is a mobile phone number.
503
+ */
504
+ IsMobile: (value) => {
505
+ if (!helper.isString(value)) {
506
+ return false;
507
+ }
508
+ return mobile(value);
509
+ },
510
+ /**
511
+ * Checks if value is a plateNumber.
512
+ */
513
+ IsPlateNumber: (value) => {
514
+ if (!helper.isString(value)) {
515
+ return false;
516
+ }
517
+ return plateNumber(value);
518
+ },
519
+ /**
520
+ * Checks value is not empty, undefined, null, '', NaN, [], {} and any empty string(including spaces,
521
+ * tabs, formfeeds, etc.), returns false
522
+ */
523
+ IsNotEmpty: (value) => {
524
+ return !helper.isEmpty(value);
525
+ }
526
+ };
527
+ /**
528
+ * Use functions or built-in rules for validation.
529
+ *
530
+ * @export
531
+ * @param {string} name
532
+ * @param {*} value
533
+ * @param {string} type
534
+ * @param {(ValidRules | ValidRules[] | Function)} rule
535
+ * @param {string} [message]
536
+ * @param {boolean} [checkType=true]
537
+ * @returns
538
+ */
539
+ function ValidatorFuncs(name, value, type, rule, message, checkType = true) {
540
+ // check type
541
+ if (checkType && !checkParamsType(value, type)) {
542
+ const err = new Error(`TypeError: invalid arguments '${name}'.`);
543
+ err.code = 400;
544
+ err.status = 400;
545
+ throw err;
546
+ }
547
+ if (helper.isFunction(rule)) {
548
+ if (!rule(value)) {
549
+ const err = new Error(message || `ValidatorError: invalid arguments[${name}].`);
550
+ err.code = 400;
551
+ err.status = 400;
552
+ throw err;
553
+ }
554
+ return value;
555
+ }
556
+ else {
557
+ const funcs = rule;
558
+ if (helper.isString(rule)) {
559
+ funcs.push(rule);
560
+ }
561
+ if (funcs.some((it) => FunctionValidator[it] && !FunctionValidator[it](value))) {
562
+ const err = new Error(message || `ValidatorError: invalid arguments[${name}].`);
563
+ err.code = 400;
564
+ err.status = 400;
565
+ throw err;
566
+ }
567
+ }
568
+ return value;
569
+ }
570
+
571
+ /*
572
+ * @Description:
573
+ * @Usage:
574
+ * @Author: richen
575
+ * @Date: 2021-11-25 10:46:57
576
+ * @LastEditTime: 2022-02-16 18:17:22
577
+ */
578
+ /**
579
+ * Validation parameter's type and values.
580
+ *
581
+ * @export
582
+ * @param {(ValidRules | ValidRules[] | Function)} rule
583
+ * @param {string} [message]
584
+ * @returns {ParameterDecorator}
585
+ */
586
+ function Valid(rule, message) {
587
+ let rules = [];
588
+ if (helper.isString(rule)) {
589
+ rules = rule.split(",");
590
+ }
591
+ else {
592
+ rules = rule;
593
+ }
594
+ return (target, propertyKey, descriptor) => {
595
+ // 获取成员参数类型
596
+ const paramTypes = Reflect.getMetadata("design:paramtypes", target, propertyKey);
597
+ const type = (paramTypes[descriptor] && paramTypes[descriptor].name) ? paramTypes[descriptor].name : "object";
598
+ IOCContainer.attachPropertyData(PARAM_RULE_KEY, {
599
+ name: propertyKey,
600
+ rule: rules,
601
+ message,
602
+ index: descriptor,
603
+ type
604
+ }, target, propertyKey);
605
+ };
606
+ }
607
+ /**
608
+ * Validation parameter's type and values from DTO class.
609
+ *
610
+ * @export
611
+ * @returns {MethodDecorator}
612
+ */
613
+ function Validated() {
614
+ return (target, propertyKey, descriptor) => {
615
+ //
616
+ IOCContainer.savePropertyData(PARAM_CHECK_KEY, {
617
+ dtoCheck: 1
618
+ }, target, propertyKey);
619
+ // 获取成员参数类型
620
+ // const paramTypes = Reflect.getMetadata("design:paramtypes", target, propertyKey) || [];
621
+ // const { value, configurable, enumerable } = descriptor;
622
+ // descriptor = {
623
+ // configurable,
624
+ // enumerable,
625
+ // writable: true,
626
+ // value: async function valid(...props: any[]) {
627
+ // const ps: any[] = [];
628
+ // // tslint:disable-next-line: no-unused-expression
629
+ // (props || []).map((value: any, index: number) => {
630
+ // const type = (paramTypes[index] && paramTypes[index].name) ? paramTypes[index].name : "any";
631
+ // if (!paramterTypes[type]) {
632
+ // ps.push(ClassValidator.valid(paramTypes[index], value, true));
633
+ // } else {
634
+ // ps.push(Promise.resolve(value));
635
+ // }
636
+ // });
637
+ // if (ps.length > 0) {
638
+ // props = await Promise.all(ps);
639
+ // }
640
+ // // tslint:disable-next-line: no-invalid-this
641
+ // return value.apply(this, props);
642
+ // }
643
+ // };
644
+ // return descriptor;
645
+ };
646
+ }
647
+ /**
648
+ * Marks property as included in the process of transformation.
649
+ *
650
+ * @export
651
+ * @returns {PropertyDecorator}
652
+ */
653
+ function Expose() {
654
+ return function (object, propertyName) {
655
+ const types = Reflect.getMetadata("design:type", object, propertyName);
656
+ if (types) {
657
+ const originMap = getOriginMetadata(PARAM_TYPE_KEY, object);
658
+ originMap.set(propertyName, types.name);
659
+ }
660
+ };
661
+ }
662
+ /**
663
+ * Identifies that the field needs to be defined
664
+ *
665
+ * @export
666
+ * @returns {PropertyDecorator}
667
+ */
668
+ function IsDefined() {
669
+ return function (object, propertyName) {
670
+ setExpose(object, propertyName);
671
+ };
672
+ }
673
+ /**
674
+ * Checks if value is a chinese name.
675
+ *
676
+ * @export
677
+ * @param {string} property
678
+ * @param {ValidationOptions} [validationOptions]
679
+ * @returns {PropertyDecorator}
680
+ */
681
+ function IsCnName(validationOptions) {
682
+ return function (object, propertyName) {
683
+ setExpose(object, propertyName);
684
+ registerDecorator({
685
+ name: "IsCnName",
686
+ target: object.constructor,
687
+ propertyName,
688
+ options: validationOptions,
689
+ validator: {
690
+ validate(value, args) {
691
+ return cnName(value);
692
+ },
693
+ defaultMessage(args) {
694
+ return "invalid parameter ($property).";
695
+ }
696
+ }
697
+ });
698
+ };
699
+ }
700
+ /**
701
+ * Checks if value is a idCard number(chinese).
702
+ *
703
+ * @export
704
+ * @param {string} property
705
+ * @param {ValidationOptions} [validationOptions]
706
+ * @returns {PropertyDecorator}
707
+ */
708
+ function IsIdNumber(validationOptions) {
709
+ return function (object, propertyName) {
710
+ setExpose(object, propertyName);
711
+ registerDecorator({
712
+ name: "IsIdNumber",
713
+ target: object.constructor,
714
+ propertyName,
715
+ options: validationOptions,
716
+ validator: {
717
+ validate(value, args) {
718
+ return idNumber(value);
719
+ },
720
+ defaultMessage(args) {
721
+ return "invalid parameter ($property).";
722
+ }
723
+ }
724
+ });
725
+ };
726
+ }
727
+ /**
728
+ * Checks if value is a zipCode(chinese).
729
+ *
730
+ * @export
731
+ * @param {string} property
732
+ * @param {ValidationOptions} [validationOptions]
733
+ * @returns {PropertyDecorator}
734
+ */
735
+ function IsZipCode(validationOptions) {
736
+ return function (object, propertyName) {
737
+ setExpose(object, propertyName);
738
+ registerDecorator({
739
+ name: "IsZipCode",
740
+ target: object.constructor,
741
+ propertyName,
742
+ options: validationOptions,
743
+ validator: {
744
+ validate(value, args) {
745
+ return zipCode(value);
746
+ },
747
+ defaultMessage(args) {
748
+ return "invalid parameter ($property).";
749
+ }
750
+ }
751
+ });
752
+ };
753
+ }
754
+ /**
755
+ * Checks if value is a mobile phone number(chinese).
756
+ *
757
+ * @export
758
+ * @param {string} property
759
+ * @param {ValidationOptions} [validationOptions]
760
+ * @returns {PropertyDecorator}
761
+ */
762
+ function IsMobile(validationOptions) {
763
+ return function (object, propertyName) {
764
+ setExpose(object, propertyName);
765
+ registerDecorator({
766
+ name: "IsMobile",
767
+ target: object.constructor,
768
+ propertyName,
769
+ options: validationOptions,
770
+ validator: {
771
+ validate(value, args) {
772
+ return mobile(value);
773
+ },
774
+ defaultMessage(args) {
775
+ return "invalid parameter ($property).";
776
+ }
777
+ }
778
+ });
779
+ };
780
+ }
781
+ /**
782
+ * Checks if value is a plate number(chinese).
783
+ *
784
+ * @export
785
+ * @param {string} property
786
+ * @param {ValidationOptions} [validationOptions]
787
+ * @returns {PropertyDecorator}
788
+ */
789
+ function IsPlateNumber(validationOptions) {
790
+ return function (object, propertyName) {
791
+ setExpose(object, propertyName);
792
+ registerDecorator({
793
+ name: "IsPlateNumber",
794
+ target: object.constructor,
795
+ propertyName,
796
+ options: validationOptions,
797
+ validator: {
798
+ validate(value, args) {
799
+ return plateNumber(value);
800
+ },
801
+ defaultMessage(args) {
802
+ return "invalid parameter ($property).";
803
+ }
804
+ }
805
+ });
806
+ };
807
+ }
808
+ /**
809
+ * Checks value is not empty, undefined, null, '', NaN, [], {} and any empty string(including spaces, tabs, formfeeds, etc.), returns false.
810
+ *
811
+ * @export
812
+ * @param {ValidationOptions} [validationOptions]
813
+ * @returns {PropertyDecorator}
814
+ */
815
+ function IsNotEmpty(validationOptions) {
816
+ return function (object, propertyName) {
817
+ setExpose(object, propertyName);
818
+ registerDecorator({
819
+ name: "IsNotEmpty",
820
+ target: object.constructor,
821
+ propertyName,
822
+ options: validationOptions,
823
+ validator: {
824
+ validate(value, args) {
825
+ return !helper.isEmpty(value);
826
+ },
827
+ defaultMessage(args) {
828
+ return "invalid parameter ($property).";
829
+ }
830
+ }
831
+ });
832
+ };
833
+ }
834
+ /**
835
+ * Checks if value matches ("===") the comparison.
836
+ *
837
+ * @export
838
+ * @param {*} comparison
839
+ * @param {ValidationOptions} [validationOptions]
840
+ * @returns {PropertyDecorator}
841
+ */
842
+ function Equals(comparison, validationOptions) {
843
+ return function (object, propertyName) {
844
+ setExpose(object, propertyName);
845
+ registerDecorator({
846
+ name: "vEquals",
847
+ target: object.constructor,
848
+ propertyName,
849
+ options: validationOptions,
850
+ validator: {
851
+ validate(value, args) {
852
+ return equals(value, comparison);
853
+ },
854
+ defaultMessage(args) {
855
+ return `invalid parameter, ($property) must be equals ${comparison}.`;
856
+ }
857
+ }
858
+ });
859
+ };
860
+ }
861
+ /**
862
+ * Checks if value does not match ("!==") the comparison.
863
+ *
864
+ * @export
865
+ * @param {*} comparison
866
+ * @param {ValidationOptions} [validationOptions]
867
+ * @returns {PropertyDecorator}
868
+ */
869
+ function NotEquals(comparison, validationOptions) {
870
+ return function (object, propertyName) {
871
+ setExpose(object, propertyName);
872
+ registerDecorator({
873
+ name: "vNotEquals",
874
+ target: object.constructor,
875
+ propertyName,
876
+ options: validationOptions,
877
+ validator: {
878
+ validate(value, args) {
879
+ return notEquals(value, comparison);
880
+ },
881
+ defaultMessage(args) {
882
+ return `invalid parameter, ($property) must be not equals ${comparison}.`;
883
+ }
884
+ }
885
+ });
886
+ };
887
+ }
888
+ /**
889
+ * Checks if the string contains the seed.
890
+ *
891
+ * @export
892
+ * @param {string} seed
893
+ * @param {ValidationOptions} [validationOptions]
894
+ * @returns {PropertyDecorator}
895
+ */
896
+ function Contains(seed, validationOptions) {
897
+ return function (object, propertyName) {
898
+ setExpose(object, propertyName);
899
+ registerDecorator({
900
+ name: "vContains",
901
+ target: object.constructor,
902
+ propertyName,
903
+ options: validationOptions,
904
+ validator: {
905
+ validate(value, args) {
906
+ return contains(value, seed);
907
+ // return typeof value === "string" && (value.indexOf(seed) > -1);
908
+ },
909
+ defaultMessage(args) {
910
+ return `invalid parameter, ($property) must be contains ${seed}.`;
911
+ }
912
+ }
913
+ });
914
+ };
915
+ }
916
+ /**
917
+ * Checks if given value is in a array of allowed values.
918
+ *
919
+ * @export
920
+ * @param {any[]} possibleValues
921
+ * @param {ValidationOptions} [validationOptions]
922
+ * @returns {PropertyDecorator}
923
+ */
924
+ function IsIn(possibleValues, validationOptions) {
925
+ return function (object, propertyName) {
926
+ setExpose(object, propertyName);
927
+ registerDecorator({
928
+ name: "vIsIn",
929
+ target: object.constructor,
930
+ propertyName,
931
+ options: validationOptions,
932
+ validator: {
933
+ validate(value, args) {
934
+ return isIn(value, possibleValues);
935
+ },
936
+ defaultMessage(args) {
937
+ return `invalid parameter ($property).`;
938
+ }
939
+ }
940
+ });
941
+ };
942
+ }
943
+ /**
944
+ * Checks if given value not in a array of allowed values.
945
+ *
946
+ * @export
947
+ * @param {any[]} possibleValues
948
+ * @param {ValidationOptions} [validationOptions]
949
+ * @returns {PropertyDecorator}
950
+ */
951
+ function IsNotIn(possibleValues, validationOptions) {
952
+ return function (object, propertyName) {
953
+ setExpose(object, propertyName);
954
+ registerDecorator({
955
+ name: "vIsNotIn",
956
+ target: object.constructor,
957
+ propertyName,
958
+ options: validationOptions,
959
+ validator: {
960
+ validate(value, args) {
961
+ return isNotIn(value, possibleValues);
962
+ },
963
+ defaultMessage(args) {
964
+ return `invalid parameter ($property).`;
965
+ }
966
+ }
967
+ });
968
+ };
969
+ }
970
+ /**
971
+ * Checks if a given value is a real date.
972
+ *
973
+ * @export
974
+ * @param {ValidationOptions} [validationOptions]
975
+ * @returns {PropertyDecorator}
976
+ */
977
+ function IsDate(validationOptions) {
978
+ return function (object, propertyName) {
979
+ setExpose(object, propertyName);
980
+ registerDecorator({
981
+ name: "vIsDate",
982
+ target: object.constructor,
983
+ propertyName,
984
+ options: validationOptions,
985
+ validator: {
986
+ validate(value, args) {
987
+ return isDate(value);
988
+ },
989
+ defaultMessage(args) {
990
+ return `invalid parameter ($property).`;
991
+ }
992
+ }
993
+ });
994
+ };
995
+ }
996
+ /**
997
+ * Checks if the first number is greater than or equal to the min value.
998
+ *
999
+ * @export
1000
+ * @param {number} min
1001
+ * @param {ValidationOptions} [validationOptions]
1002
+ * @returns {PropertyDecorator}
1003
+ */
1004
+ function Min(min, validationOptions) {
1005
+ return function (object, propertyName) {
1006
+ setExpose(object, propertyName);
1007
+ registerDecorator({
1008
+ name: "vMin",
1009
+ target: object.constructor,
1010
+ propertyName,
1011
+ options: validationOptions,
1012
+ validator: {
1013
+ validate(value, args) {
1014
+ return helper.toNumber(value) >= min;
1015
+ },
1016
+ defaultMessage(args) {
1017
+ return `invalid parameter ($property).`;
1018
+ }
1019
+ }
1020
+ });
1021
+ };
1022
+ }
1023
+ /**
1024
+ * Checks if the first number is less than or equal to the max value.
1025
+ *
1026
+ * @export
1027
+ * @param {number} max
1028
+ * @param {ValidationOptions} [validationOptions]
1029
+ * @returns {PropertyDecorator}
1030
+ */
1031
+ function Max(max, validationOptions) {
1032
+ return function (object, propertyName) {
1033
+ setExpose(object, propertyName);
1034
+ registerDecorator({
1035
+ name: "vMax",
1036
+ target: object.constructor,
1037
+ propertyName,
1038
+ options: validationOptions,
1039
+ validator: {
1040
+ validate(value, args) {
1041
+ return helper.toNumber(value) <= max;
1042
+ },
1043
+ defaultMessage(args) {
1044
+ return `invalid parameter ($property).`;
1045
+ }
1046
+ }
1047
+ });
1048
+ };
1049
+ }
1050
+ /**
1051
+ * Checks if the string's length falls in a range. Note: this function takes into account surrogate pairs.
1052
+ * If given value is not a string, then it returns false.
1053
+ *
1054
+ * @export
1055
+ * @param {number} min
1056
+ * @param {number} [max]
1057
+ * @param {ValidationOptions} [validationOptions]
1058
+ * @returns {PropertyDecorator}
1059
+ */
1060
+ function Length(min, max, validationOptions) {
1061
+ return function (object, propertyName) {
1062
+ setExpose(object, propertyName);
1063
+ registerDecorator({
1064
+ name: "vLength",
1065
+ target: object.constructor,
1066
+ propertyName,
1067
+ options: validationOptions,
1068
+ validator: {
1069
+ validate(value, args) {
1070
+ return length(value, min, max);
1071
+ },
1072
+ defaultMessage(args) {
1073
+ return `invalid parameter ($property).`;
1074
+ }
1075
+ }
1076
+ });
1077
+ };
1078
+ }
1079
+ /**
1080
+ * Checks if the string is an email. If given value is not a string, then it returns false.
1081
+ *
1082
+ * @export
1083
+ * @param {IsEmailOptions} [options]
1084
+ * @param {ValidationOptions} [validationOptions]
1085
+ * @returns {PropertyDecorator}
1086
+ */
1087
+ function IsEmail(options, validationOptions) {
1088
+ return function (object, propertyName) {
1089
+ setExpose(object, propertyName);
1090
+ registerDecorator({
1091
+ name: "vIsEmail",
1092
+ target: object.constructor,
1093
+ propertyName,
1094
+ options: validationOptions,
1095
+ validator: {
1096
+ validate(value, args) {
1097
+ return isEmail(value);
1098
+ },
1099
+ defaultMessage(args) {
1100
+ return `invalid parameter ($property).`;
1101
+ }
1102
+ }
1103
+ });
1104
+ };
1105
+ }
1106
+ /**
1107
+ * Checks if the string is an IP (version 4 or 6). If given value is not a string, then it returns false.
1108
+ *
1109
+ * @export
1110
+ * @param {number} [version]
1111
+ * @param {ValidationOptions} [validationOptions]
1112
+ * @returns {PropertyDecorator}
1113
+ */
1114
+ function IsIP(version, validationOptions) {
1115
+ return function (object, propertyName) {
1116
+ setExpose(object, propertyName);
1117
+ registerDecorator({
1118
+ name: "vIsIP",
1119
+ target: object.constructor,
1120
+ propertyName,
1121
+ options: validationOptions,
1122
+ validator: {
1123
+ validate(value, args) {
1124
+ return isIP(value, version);
1125
+ },
1126
+ defaultMessage(args) {
1127
+ return `invalid parameter ($property).`;
1128
+ }
1129
+ }
1130
+ });
1131
+ };
1132
+ }
1133
+ /**
1134
+ * Checks if the string is a valid phone number.
1135
+ *
1136
+ * @export
1137
+ * @param {string} {string} region 2 characters uppercase country code (e.g. DE, US, CH).
1138
+ * If users must enter the intl. prefix (e.g. +41), then you may pass "ZZ" or null as region.
1139
+ * See [google-libphonenumber, metadata.js:countryCodeToRegionCodeMap on github]
1140
+ * {@link https://github.com/ruimarinho/google-libphonenumber/blob/1e46138878cff479aafe2ce62175c6c49cb58720/src/metadata.js#L33}
1141
+ * @param {ValidationOptions} [validationOptions]
1142
+ * @returns {PropertyDecorator}
1143
+ */
1144
+ function IsPhoneNumber(region, validationOptions) {
1145
+ return function (object, propertyName) {
1146
+ setExpose(object, propertyName);
1147
+ registerDecorator({
1148
+ name: "vIsPhoneNumber",
1149
+ target: object.constructor,
1150
+ propertyName,
1151
+ options: validationOptions,
1152
+ validator: {
1153
+ validate(value, args) {
1154
+ return isPhoneNumber(value, region);
1155
+ },
1156
+ defaultMessage(args) {
1157
+ return `invalid parameter ($property).`;
1158
+ }
1159
+ }
1160
+ });
1161
+ };
1162
+ }
1163
+ /**
1164
+ * Checks if the string is an url.
1165
+ *
1166
+ * @export
1167
+ * @param {IsURLOptions} [options]
1168
+ * @param {ValidationOptions} [validationOptions]
1169
+ * @returns {PropertyDecorator}
1170
+ */
1171
+ function IsUrl(options, validationOptions) {
1172
+ return function (object, propertyName) {
1173
+ setExpose(object, propertyName);
1174
+ registerDecorator({
1175
+ name: "vIsUrl",
1176
+ target: object.constructor,
1177
+ propertyName,
1178
+ options: validationOptions,
1179
+ validator: {
1180
+ validate(value, args) {
1181
+ return isURL(value, options);
1182
+ },
1183
+ defaultMessage(args) {
1184
+ return `invalid parameter ($property).`;
1185
+ }
1186
+ }
1187
+ });
1188
+ };
1189
+ }
1190
+ /**
1191
+ * check if the string is a hash of type algorithm. Algorithm is one of ['md4', 'md5', 'sha1', 'sha256',
1192
+ * 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', 'tiger160', 'tiger192', 'crc32', 'crc32b']
1193
+ *
1194
+ * @export
1195
+ * @param {HashAlgorithm} algorithm
1196
+ * @param {ValidationOptions} [validationOptions]
1197
+ * @returns {PropertyDecorator}
1198
+ */
1199
+ function IsHash(algorithm, validationOptions) {
1200
+ return function (object, propertyName) {
1201
+ setExpose(object, propertyName);
1202
+ registerDecorator({
1203
+ name: "vIsHash",
1204
+ target: object.constructor,
1205
+ propertyName,
1206
+ options: validationOptions,
1207
+ validator: {
1208
+ validate(value, args) {
1209
+ return isHash(value, algorithm);
1210
+ },
1211
+ defaultMessage(args) {
1212
+ return `invalid parameter, ($property) must be is an ${algorithm} Hash string.`;
1213
+ }
1214
+ }
1215
+ });
1216
+ };
1217
+ }
1218
+
1219
+ export { ClassValidator, Contains, ENABLE_VALIDATED, Equals, Expose, FunctionValidator, IsCnName, IsDate, IsDefined, IsEmail, IsHash, IsIP, IsIdNumber, IsIn, IsMobile, IsNotEmpty, IsNotIn, IsPhoneNumber, IsPlateNumber, IsUrl, IsZipCode, Length, Max, Min, NotEquals, PARAM_CHECK_KEY, PARAM_RULE_KEY, PARAM_TYPE_KEY, Valid, Validated, ValidatorFuncs, checkParamsType, convertDtoParamsType, convertParamsType, paramterTypes, plainToClass };