koatty_validation 1.0.10 → 1.2.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,1326 @@
1
+ /*!
2
+ * @Author: richen
3
+ * @Date: 2022-02-25 09:58:02
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, isEmail, isIP, isPhoneNumber, isURL, isHash, equals, notEquals, contains, isIn, isNotIn, registerDecorator, isDate, length } 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: 2022-02-25 09:51:04
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 ValidFuncs = {
383
+ /**
384
+ * Checks value is not empty, undefined, null, '', NaN, [], {} and any empty string(including spaces,
385
+ * tabs, formfeeds, etc.), returns false
386
+ */
387
+ IsNotEmpty: (value) => {
388
+ return !helper.isEmpty(value);
389
+ },
390
+ /**
391
+ * Checks if a given value is a real date.
392
+ */
393
+ IsDate: (value) => {
394
+ return helper.isDate(value);
395
+ },
396
+ /**
397
+ * Checks if the string is an email. If given value is not a string, then it returns false.
398
+ */
399
+ IsEmail: (value, options) => {
400
+ return isEmail(value, options);
401
+ },
402
+ /**
403
+ * Checks if the string is an IP (version 4 or 6). If given value is not a string, then it returns false.
404
+ */
405
+ IsIP: (value, version) => {
406
+ return isIP(value, version);
407
+ },
408
+ /**
409
+ * Checks if the string is a valid phone number.
410
+ * @param value — the potential phone number string to test
411
+ * @param region 2 characters uppercase country code (e.g. DE, US, CH). If users must enter the intl.
412
+ * prefix (e.g. +41), then you may pass "ZZ" or null as region.
413
+ * See [google-libphonenumber, metadata.js:countryCodeToRegionCodeMap on github]
414
+ * {@link https://github.com/ruimarinho/google-libphonenumber/blob/1e46138878cff479aafe2ce62175c6c49cb58720/src/metadata.js#L33}
415
+ */
416
+ IsPhoneNumber: (value, region) => {
417
+ return isPhoneNumber(value, region);
418
+ },
419
+ /**
420
+ * Checks if the string is an url. If given value is not a string, then it returns false.
421
+ */
422
+ IsUrl: (value, options) => {
423
+ return isURL(value, options);
424
+ },
425
+ /**
426
+ * check if the string is a hash of type algorithm. Algorithm is one of
427
+ * ['md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', 'tiger160', 'tiger192', 'crc32', 'crc32b']
428
+ */
429
+ IsHash: (value, algorithm) => {
430
+ return isHash(value, algorithm);
431
+ },
432
+ /**
433
+ * Checks if value is a chinese name.
434
+ */
435
+ IsCnName: (value) => {
436
+ if (!helper.isString(value)) {
437
+ return false;
438
+ }
439
+ return cnName(value);
440
+ },
441
+ /**
442
+ * Checks if value is a idcard number.
443
+ */
444
+ IsIdNumber: (value) => {
445
+ if (!helper.isString(value)) {
446
+ return false;
447
+ }
448
+ return idNumber(value);
449
+ },
450
+ /**
451
+ * Checks if value is a zipCode.
452
+ */
453
+ IsZipCode: (value) => {
454
+ if (!helper.isString(value)) {
455
+ return false;
456
+ }
457
+ return zipCode(value);
458
+ },
459
+ /**
460
+ * Checks if value is a mobile phone number.
461
+ */
462
+ IsMobile: (value) => {
463
+ if (!helper.isString(value)) {
464
+ return false;
465
+ }
466
+ return mobile(value);
467
+ },
468
+ /**
469
+ * Checks if value is a plateNumber.
470
+ */
471
+ IsPlateNumber: (value) => {
472
+ if (!helper.isString(value)) {
473
+ return false;
474
+ }
475
+ return plateNumber(value);
476
+ },
477
+ /**
478
+ * Checks if value matches ("===") the comparison.
479
+ */
480
+ Equals: (value, comparison) => {
481
+ return equals(value, comparison);
482
+ },
483
+ /**
484
+ * Checks if value does not match ("!==") the comparison.
485
+ */
486
+ NotEquals: (value, comparison) => {
487
+ return notEquals(value, comparison);
488
+ },
489
+ /**
490
+ * Checks if the string contains the seed. If given value is not a string, then it returns false.
491
+ */
492
+ Contains: (value, seed) => {
493
+ return contains(value, seed);
494
+ },
495
+ /**
496
+ * Checks if given value is in a array of allowed values.
497
+ */
498
+ IsIn: (value, possibleValues) => {
499
+ return isIn(value, possibleValues);
500
+ },
501
+ /**
502
+ * Checks if given value not in a array of allowed values.
503
+ */
504
+ IsNotIn: (value, possibleValues) => {
505
+ return isNotIn(value, possibleValues);
506
+ },
507
+ /**
508
+ * Checks if the first number is greater than or equal to the second.
509
+ */
510
+ Gt: (num, min) => {
511
+ return helper.toNumber(num) > min;
512
+ },
513
+ /**
514
+ * Checks if the first number is less than or equal to the second.
515
+ */
516
+ Lt: (num, max) => {
517
+ return helper.toNumber(num) < max;
518
+ },
519
+ /**
520
+ * Checks if the first number is greater than or equal to the second.
521
+ */
522
+ Gte: (num, min) => {
523
+ return helper.toNumber(num) >= min;
524
+ },
525
+ /**
526
+ * Checks if the first number is less than or equal to the second.
527
+ */
528
+ Lte: (num, max) => {
529
+ return helper.toNumber(num) <= max;
530
+ },
531
+ };
532
+ /**
533
+ * Use functions or built-in rules for validation.
534
+ *
535
+ * @export
536
+ * @param {ValidRules} rule
537
+ * @param {unknown} value
538
+ * @param {(string | ValidOtpions)} [options]
539
+ * @returns {*}
540
+ */
541
+ const FunctionValidator = {
542
+ IsNotEmpty: function (value, options) {
543
+ throw new Error("Function not implemented.");
544
+ },
545
+ IsDate: function (value, options) {
546
+ throw new Error("Function not implemented.");
547
+ },
548
+ IsEmail: function (value, options) {
549
+ throw new Error("Function not implemented.");
550
+ },
551
+ IsIP: function (value, options) {
552
+ throw new Error("Function not implemented.");
553
+ },
554
+ IsPhoneNumber: function (value, options) {
555
+ throw new Error("Function not implemented.");
556
+ },
557
+ IsUrl: function (value, options) {
558
+ throw new Error("Function not implemented.");
559
+ },
560
+ IsHash: function (value, options) {
561
+ throw new Error("Function not implemented.");
562
+ },
563
+ IsCnName: function (value, options) {
564
+ throw new Error("Function not implemented.");
565
+ },
566
+ IsIdNumber: function (value, options) {
567
+ throw new Error("Function not implemented.");
568
+ },
569
+ IsZipCode: function (value, options) {
570
+ throw new Error("Function not implemented.");
571
+ },
572
+ IsMobile: function (value, options) {
573
+ throw new Error("Function not implemented.");
574
+ },
575
+ IsPlateNumber: function (value, options) {
576
+ throw new Error("Function not implemented.");
577
+ },
578
+ Equals: function (value, options) {
579
+ throw new Error("Function not implemented.");
580
+ },
581
+ NotEquals: function (value, options) {
582
+ throw new Error("Function not implemented.");
583
+ },
584
+ Contains: function (value, options) {
585
+ throw new Error("Function not implemented.");
586
+ },
587
+ IsIn: function (value, options) {
588
+ throw new Error("Function not implemented.");
589
+ },
590
+ IsNotIn: function (value, options) {
591
+ throw new Error("Function not implemented.");
592
+ },
593
+ Gt: function (value, options) {
594
+ throw new Error("Function not implemented.");
595
+ },
596
+ Lt: function (value, options) {
597
+ throw new Error("Function not implemented.");
598
+ },
599
+ Gte: function (value, options) {
600
+ throw new Error("Function not implemented.");
601
+ },
602
+ Lte: function (value, options) {
603
+ throw new Error("Function not implemented.");
604
+ }
605
+ };
606
+ Object.keys(ValidFuncs).forEach((key) => {
607
+ FunctionValidator[key] = (value, options) => {
608
+ if (helper.isString(options)) {
609
+ options = { message: options, value: null };
610
+ }
611
+ if (!ValidFuncs[key](value, options)) {
612
+ const err = new Error(options.message || `ValidatorError: invalid arguments.`);
613
+ err.code = 400;
614
+ err.status = 400;
615
+ throw err;
616
+ }
617
+ };
618
+ });
619
+
620
+ /*
621
+ * @Description:
622
+ * @Usage:
623
+ * @Author: richen
624
+ * @Date: 2021-11-25 10:46:57
625
+ * @LastEditTime: 2022-02-24 15:33:34
626
+ */
627
+ /**
628
+ * Validation parameter's type and values.
629
+ *
630
+ * @export
631
+ * @param {(ValidRules | ValidRules[] | Function)} rule
632
+ * @param {*} [options] If the options type is a string, the value is the error message of the validation rule.
633
+ * Some validation rules require additional parameters, ext: @Valid("Gte", {message:"Requires value greater than or equal to 100", value: 100})
634
+ * @returns {*} {ParameterDecorator}
635
+ */
636
+ function Valid(rule, options) {
637
+ let rules = [];
638
+ if (helper.isString(rule)) {
639
+ rules = rule.split(",");
640
+ }
641
+ else {
642
+ rules = rule;
643
+ }
644
+ return (target, propertyKey, descriptor) => {
645
+ // 获取成员参数类型
646
+ const paramTypes = Reflect.getMetadata("design:paramtypes", target, propertyKey);
647
+ const type = (paramTypes[descriptor] && paramTypes[descriptor].name) ? paramTypes[descriptor].name : "object";
648
+ if (helper.isString(options)) {
649
+ options = { message: options, value: null };
650
+ }
651
+ IOCContainer.attachPropertyData(PARAM_RULE_KEY, {
652
+ name: propertyKey,
653
+ rule: rules,
654
+ options,
655
+ index: descriptor,
656
+ type
657
+ }, target, propertyKey);
658
+ };
659
+ }
660
+ /**
661
+ * Validation parameter's type and values from DTO class.
662
+ *
663
+ * @export
664
+ * @returns {MethodDecorator}
665
+ */
666
+ function Validated() {
667
+ return (target, propertyKey, descriptor) => {
668
+ //
669
+ IOCContainer.savePropertyData(PARAM_CHECK_KEY, {
670
+ dtoCheck: 1
671
+ }, target, propertyKey);
672
+ // 获取成员参数类型
673
+ // const paramTypes = Reflect.getMetadata("design:paramtypes", target, propertyKey) || [];
674
+ // const { value, configurable, enumerable } = descriptor;
675
+ // descriptor = {
676
+ // configurable,
677
+ // enumerable,
678
+ // writable: true,
679
+ // value: async function valid(...props: any[]) {
680
+ // const ps: any[] = [];
681
+ // // tslint:disable-next-line: no-unused-expression
682
+ // (props || []).map((value: any, index: number) => {
683
+ // const type = (paramTypes[index] && paramTypes[index].name) ? paramTypes[index].name : "any";
684
+ // if (!paramterTypes[type]) {
685
+ // ps.push(ClassValidator.valid(paramTypes[index], value, true));
686
+ // } else {
687
+ // ps.push(Promise.resolve(value));
688
+ // }
689
+ // });
690
+ // if (ps.length > 0) {
691
+ // props = await Promise.all(ps);
692
+ // }
693
+ // // tslint:disable-next-line: no-invalid-this
694
+ // return value.apply(this, props);
695
+ // }
696
+ // };
697
+ // return descriptor;
698
+ };
699
+ }
700
+ /**
701
+ * Marks property as included in the process of transformation.
702
+ *
703
+ * @export
704
+ * @returns {PropertyDecorator}
705
+ */
706
+ function Expose() {
707
+ return function (object, propertyName) {
708
+ const types = Reflect.getMetadata("design:type", object, propertyName);
709
+ if (types) {
710
+ const originMap = getOriginMetadata(PARAM_TYPE_KEY, object);
711
+ originMap.set(propertyName, types.name);
712
+ }
713
+ };
714
+ }
715
+ /**
716
+ * Identifies that the field needs to be defined
717
+ *
718
+ * @export
719
+ * @returns {PropertyDecorator}
720
+ */
721
+ function IsDefined() {
722
+ return function (object, propertyName) {
723
+ setExpose(object, propertyName);
724
+ };
725
+ }
726
+ /**
727
+ * Checks if value is a chinese name.
728
+ *
729
+ * @export
730
+ * @param {string} property
731
+ * @param {ValidationOptions} [validationOptions]
732
+ * @returns {PropertyDecorator}
733
+ */
734
+ function IsCnName(validationOptions) {
735
+ return function (object, propertyName) {
736
+ setExpose(object, propertyName);
737
+ registerDecorator({
738
+ name: "IsCnName",
739
+ target: object.constructor,
740
+ propertyName,
741
+ options: validationOptions,
742
+ validator: {
743
+ validate(value, args) {
744
+ return cnName(value);
745
+ },
746
+ defaultMessage(args) {
747
+ return "invalid parameter ($property).";
748
+ }
749
+ }
750
+ });
751
+ };
752
+ }
753
+ /**
754
+ * Checks if value is a idCard number(chinese).
755
+ *
756
+ * @export
757
+ * @param {string} property
758
+ * @param {ValidationOptions} [validationOptions]
759
+ * @returns {PropertyDecorator}
760
+ */
761
+ function IsIdNumber(validationOptions) {
762
+ return function (object, propertyName) {
763
+ setExpose(object, propertyName);
764
+ registerDecorator({
765
+ name: "IsIdNumber",
766
+ target: object.constructor,
767
+ propertyName,
768
+ options: validationOptions,
769
+ validator: {
770
+ validate(value, args) {
771
+ return idNumber(value);
772
+ },
773
+ defaultMessage(args) {
774
+ return "invalid parameter ($property).";
775
+ }
776
+ }
777
+ });
778
+ };
779
+ }
780
+ /**
781
+ * Checks if value is a zipCode(chinese).
782
+ *
783
+ * @export
784
+ * @param {string} property
785
+ * @param {ValidationOptions} [validationOptions]
786
+ * @returns {PropertyDecorator}
787
+ */
788
+ function IsZipCode(validationOptions) {
789
+ return function (object, propertyName) {
790
+ setExpose(object, propertyName);
791
+ registerDecorator({
792
+ name: "IsZipCode",
793
+ target: object.constructor,
794
+ propertyName,
795
+ options: validationOptions,
796
+ validator: {
797
+ validate(value, args) {
798
+ return zipCode(value);
799
+ },
800
+ defaultMessage(args) {
801
+ return "invalid parameter ($property).";
802
+ }
803
+ }
804
+ });
805
+ };
806
+ }
807
+ /**
808
+ * Checks if value is a mobile phone number(chinese).
809
+ *
810
+ * @export
811
+ * @param {string} property
812
+ * @param {ValidationOptions} [validationOptions]
813
+ * @returns {PropertyDecorator}
814
+ */
815
+ function IsMobile(validationOptions) {
816
+ return function (object, propertyName) {
817
+ setExpose(object, propertyName);
818
+ registerDecorator({
819
+ name: "IsMobile",
820
+ target: object.constructor,
821
+ propertyName,
822
+ options: validationOptions,
823
+ validator: {
824
+ validate(value, args) {
825
+ return mobile(value);
826
+ },
827
+ defaultMessage(args) {
828
+ return "invalid parameter ($property).";
829
+ }
830
+ }
831
+ });
832
+ };
833
+ }
834
+ /**
835
+ * Checks if value is a plate number(chinese).
836
+ *
837
+ * @export
838
+ * @param {string} property
839
+ * @param {ValidationOptions} [validationOptions]
840
+ * @returns {PropertyDecorator}
841
+ */
842
+ function IsPlateNumber(validationOptions) {
843
+ return function (object, propertyName) {
844
+ setExpose(object, propertyName);
845
+ registerDecorator({
846
+ name: "IsPlateNumber",
847
+ target: object.constructor,
848
+ propertyName,
849
+ options: validationOptions,
850
+ validator: {
851
+ validate(value, args) {
852
+ return plateNumber(value);
853
+ },
854
+ defaultMessage(args) {
855
+ return "invalid parameter ($property).";
856
+ }
857
+ }
858
+ });
859
+ };
860
+ }
861
+ /**
862
+ * Checks value is not empty, undefined, null, '', NaN, [], {} and any empty string(including spaces, tabs, formfeeds, etc.), returns false.
863
+ *
864
+ * @export
865
+ * @param {ValidationOptions} [validationOptions]
866
+ * @returns {PropertyDecorator}
867
+ */
868
+ function IsNotEmpty(validationOptions) {
869
+ return function (object, propertyName) {
870
+ setExpose(object, propertyName);
871
+ registerDecorator({
872
+ name: "IsNotEmpty",
873
+ target: object.constructor,
874
+ propertyName,
875
+ options: validationOptions,
876
+ validator: {
877
+ validate(value, args) {
878
+ return !helper.isEmpty(value);
879
+ },
880
+ defaultMessage(args) {
881
+ return "invalid parameter ($property).";
882
+ }
883
+ }
884
+ });
885
+ };
886
+ }
887
+ /**
888
+ * Checks if value matches ("===") the comparison.
889
+ *
890
+ * @export
891
+ * @param {*} comparison
892
+ * @param {ValidationOptions} [validationOptions]
893
+ * @returns {PropertyDecorator}
894
+ */
895
+ function Equals(comparison, validationOptions) {
896
+ return function (object, propertyName) {
897
+ setExpose(object, propertyName);
898
+ registerDecorator({
899
+ name: "vEquals",
900
+ target: object.constructor,
901
+ propertyName,
902
+ options: validationOptions,
903
+ validator: {
904
+ validate(value, args) {
905
+ return equals(value, comparison);
906
+ },
907
+ defaultMessage(args) {
908
+ return `invalid parameter, ($property) must be equals ${comparison}.`;
909
+ }
910
+ }
911
+ });
912
+ };
913
+ }
914
+ /**
915
+ * Checks if value does not match ("!==") the comparison.
916
+ *
917
+ * @export
918
+ * @param {*} comparison
919
+ * @param {ValidationOptions} [validationOptions]
920
+ * @returns {PropertyDecorator}
921
+ */
922
+ function NotEquals(comparison, validationOptions) {
923
+ return function (object, propertyName) {
924
+ setExpose(object, propertyName);
925
+ registerDecorator({
926
+ name: "vNotEquals",
927
+ target: object.constructor,
928
+ propertyName,
929
+ options: validationOptions,
930
+ validator: {
931
+ validate(value, args) {
932
+ return notEquals(value, comparison);
933
+ },
934
+ defaultMessage(args) {
935
+ return `invalid parameter, ($property) must be not equals ${comparison}.`;
936
+ }
937
+ }
938
+ });
939
+ };
940
+ }
941
+ /**
942
+ * Checks if the string contains the seed.
943
+ *
944
+ * @export
945
+ * @param {string} seed
946
+ * @param {ValidationOptions} [validationOptions]
947
+ * @returns {PropertyDecorator}
948
+ */
949
+ function Contains(seed, validationOptions) {
950
+ return function (object, propertyName) {
951
+ setExpose(object, propertyName);
952
+ registerDecorator({
953
+ name: "vContains",
954
+ target: object.constructor,
955
+ propertyName,
956
+ options: validationOptions,
957
+ validator: {
958
+ validate(value, args) {
959
+ return contains(value, seed);
960
+ // return typeof value === "string" && (value.indexOf(seed) > -1);
961
+ },
962
+ defaultMessage(args) {
963
+ return `invalid parameter, ($property) must be contains ${seed}.`;
964
+ }
965
+ }
966
+ });
967
+ };
968
+ }
969
+ /**
970
+ * Checks if given value is in a array of allowed values.
971
+ *
972
+ * @export
973
+ * @param {any[]} possibleValues
974
+ * @param {ValidationOptions} [validationOptions]
975
+ * @returns {PropertyDecorator}
976
+ */
977
+ function IsIn(possibleValues, validationOptions) {
978
+ return function (object, propertyName) {
979
+ setExpose(object, propertyName);
980
+ registerDecorator({
981
+ name: "vIsIn",
982
+ target: object.constructor,
983
+ propertyName,
984
+ options: validationOptions,
985
+ validator: {
986
+ validate(value, args) {
987
+ return isIn(value, possibleValues);
988
+ },
989
+ defaultMessage(args) {
990
+ return `invalid parameter ($property).`;
991
+ }
992
+ }
993
+ });
994
+ };
995
+ }
996
+ /**
997
+ * Checks if given value not in a array of allowed values.
998
+ *
999
+ * @export
1000
+ * @param {any[]} possibleValues
1001
+ * @param {ValidationOptions} [validationOptions]
1002
+ * @returns {PropertyDecorator}
1003
+ */
1004
+ function IsNotIn(possibleValues, validationOptions) {
1005
+ return function (object, propertyName) {
1006
+ setExpose(object, propertyName);
1007
+ registerDecorator({
1008
+ name: "vIsNotIn",
1009
+ target: object.constructor,
1010
+ propertyName,
1011
+ options: validationOptions,
1012
+ validator: {
1013
+ validate(value, args) {
1014
+ return isNotIn(value, possibleValues);
1015
+ },
1016
+ defaultMessage(args) {
1017
+ return `invalid parameter ($property).`;
1018
+ }
1019
+ }
1020
+ });
1021
+ };
1022
+ }
1023
+ /**
1024
+ * Checks if a given value is a real date.
1025
+ *
1026
+ * @export
1027
+ * @param {ValidationOptions} [validationOptions]
1028
+ * @returns {PropertyDecorator}
1029
+ */
1030
+ function IsDate(validationOptions) {
1031
+ return function (object, propertyName) {
1032
+ setExpose(object, propertyName);
1033
+ registerDecorator({
1034
+ name: "vIsDate",
1035
+ target: object.constructor,
1036
+ propertyName,
1037
+ options: validationOptions,
1038
+ validator: {
1039
+ validate(value, args) {
1040
+ return isDate(value);
1041
+ },
1042
+ defaultMessage(args) {
1043
+ return `invalid parameter ($property).`;
1044
+ }
1045
+ }
1046
+ });
1047
+ };
1048
+ }
1049
+ /**
1050
+ * Checks if the first number is greater than or equal to the min value.
1051
+ *
1052
+ * @export
1053
+ * @param {number} min
1054
+ * @param {ValidationOptions} [validationOptions]
1055
+ * @returns {PropertyDecorator}
1056
+ */
1057
+ function Gt(min, validationOptions) {
1058
+ return function (object, propertyName) {
1059
+ setExpose(object, propertyName);
1060
+ registerDecorator({
1061
+ name: "vMin",
1062
+ target: object.constructor,
1063
+ propertyName,
1064
+ options: validationOptions,
1065
+ validator: {
1066
+ validate(value, args) {
1067
+ return helper.toNumber(value) > min;
1068
+ },
1069
+ defaultMessage(args) {
1070
+ return `invalid parameter ($property).`;
1071
+ }
1072
+ }
1073
+ });
1074
+ };
1075
+ }
1076
+ /**
1077
+ * Checks if the first number is less than or equal to the max value.
1078
+ *
1079
+ * @export
1080
+ * @param {number} max
1081
+ * @param {ValidationOptions} [validationOptions]
1082
+ * @returns {PropertyDecorator}
1083
+ */
1084
+ function Lt(max, validationOptions) {
1085
+ return function (object, propertyName) {
1086
+ setExpose(object, propertyName);
1087
+ registerDecorator({
1088
+ name: "vMax",
1089
+ target: object.constructor,
1090
+ propertyName,
1091
+ options: validationOptions,
1092
+ validator: {
1093
+ validate(value, args) {
1094
+ return helper.toNumber(value) < max;
1095
+ },
1096
+ defaultMessage(args) {
1097
+ return `invalid parameter ($property).`;
1098
+ }
1099
+ }
1100
+ });
1101
+ };
1102
+ }
1103
+ /**
1104
+ * Checks if the first number is greater than or equal to the min value.
1105
+ *
1106
+ * @export
1107
+ * @param {number} min
1108
+ * @param {ValidationOptions} [validationOptions]
1109
+ * @returns {PropertyDecorator}
1110
+ */
1111
+ function Gte(min, validationOptions) {
1112
+ return function (object, propertyName) {
1113
+ setExpose(object, propertyName);
1114
+ registerDecorator({
1115
+ name: "vMin",
1116
+ target: object.constructor,
1117
+ propertyName,
1118
+ options: validationOptions,
1119
+ validator: {
1120
+ validate(value, args) {
1121
+ return helper.toNumber(value) >= min;
1122
+ },
1123
+ defaultMessage(args) {
1124
+ return `invalid parameter ($property).`;
1125
+ }
1126
+ }
1127
+ });
1128
+ };
1129
+ }
1130
+ /**
1131
+ * Checks if the first number is less than or equal to the max value.
1132
+ *
1133
+ * @export
1134
+ * @param {number} max
1135
+ * @param {ValidationOptions} [validationOptions]
1136
+ * @returns {PropertyDecorator}
1137
+ */
1138
+ function Lte(max, validationOptions) {
1139
+ return function (object, propertyName) {
1140
+ setExpose(object, propertyName);
1141
+ registerDecorator({
1142
+ name: "vMax",
1143
+ target: object.constructor,
1144
+ propertyName,
1145
+ options: validationOptions,
1146
+ validator: {
1147
+ validate(value, args) {
1148
+ return helper.toNumber(value) <= max;
1149
+ },
1150
+ defaultMessage(args) {
1151
+ return `invalid parameter ($property).`;
1152
+ }
1153
+ }
1154
+ });
1155
+ };
1156
+ }
1157
+ /**
1158
+ * Checks if the string's length falls in a range. Note: this function takes into account surrogate pairs.
1159
+ * If given value is not a string, then it returns false.
1160
+ *
1161
+ * @export
1162
+ * @param {number} min
1163
+ * @param {number} [max]
1164
+ * @param {ValidationOptions} [validationOptions]
1165
+ * @returns {PropertyDecorator}
1166
+ */
1167
+ function Length(min, max, validationOptions) {
1168
+ return function (object, propertyName) {
1169
+ setExpose(object, propertyName);
1170
+ registerDecorator({
1171
+ name: "vLength",
1172
+ target: object.constructor,
1173
+ propertyName,
1174
+ options: validationOptions,
1175
+ validator: {
1176
+ validate(value, args) {
1177
+ return length(value, min, max);
1178
+ },
1179
+ defaultMessage(args) {
1180
+ return `invalid parameter ($property).`;
1181
+ }
1182
+ }
1183
+ });
1184
+ };
1185
+ }
1186
+ /**
1187
+ * Checks if the string is an email. If given value is not a string, then it returns false.
1188
+ *
1189
+ * @export
1190
+ * @param {IsEmailOptions} [options]
1191
+ * @param {ValidationOptions} [validationOptions]
1192
+ * @returns {PropertyDecorator}
1193
+ */
1194
+ function IsEmail(options, validationOptions) {
1195
+ return function (object, propertyName) {
1196
+ setExpose(object, propertyName);
1197
+ registerDecorator({
1198
+ name: "vIsEmail",
1199
+ target: object.constructor,
1200
+ propertyName,
1201
+ options: validationOptions,
1202
+ validator: {
1203
+ validate(value, args) {
1204
+ return isEmail(value);
1205
+ },
1206
+ defaultMessage(args) {
1207
+ return `invalid parameter ($property).`;
1208
+ }
1209
+ }
1210
+ });
1211
+ };
1212
+ }
1213
+ /**
1214
+ * Checks if the string is an IP (version 4 or 6). If given value is not a string, then it returns false.
1215
+ *
1216
+ * @export
1217
+ * @param {number} [version]
1218
+ * @param {ValidationOptions} [validationOptions]
1219
+ * @returns {PropertyDecorator}
1220
+ */
1221
+ function IsIP(version, validationOptions) {
1222
+ return function (object, propertyName) {
1223
+ setExpose(object, propertyName);
1224
+ registerDecorator({
1225
+ name: "vIsIP",
1226
+ target: object.constructor,
1227
+ propertyName,
1228
+ options: validationOptions,
1229
+ validator: {
1230
+ validate(value, args) {
1231
+ return isIP(value, version);
1232
+ },
1233
+ defaultMessage(args) {
1234
+ return `invalid parameter ($property).`;
1235
+ }
1236
+ }
1237
+ });
1238
+ };
1239
+ }
1240
+ /**
1241
+ * Checks if the string is a valid phone number.
1242
+ *
1243
+ * @export
1244
+ * @param {string} {string} region 2 characters uppercase country code (e.g. DE, US, CH).
1245
+ * If users must enter the intl. prefix (e.g. +41), then you may pass "ZZ" or null as region.
1246
+ * See [google-libphonenumber, metadata.js:countryCodeToRegionCodeMap on github]
1247
+ * {@link https://github.com/ruimarinho/google-libphonenumber/blob/1e46138878cff479aafe2ce62175c6c49cb58720/src/metadata.js#L33}
1248
+ * @param {ValidationOptions} [validationOptions]
1249
+ * @returns {PropertyDecorator}
1250
+ */
1251
+ function IsPhoneNumber(region, validationOptions) {
1252
+ return function (object, propertyName) {
1253
+ setExpose(object, propertyName);
1254
+ registerDecorator({
1255
+ name: "vIsPhoneNumber",
1256
+ target: object.constructor,
1257
+ propertyName,
1258
+ options: validationOptions,
1259
+ validator: {
1260
+ validate(value, args) {
1261
+ return isPhoneNumber(value, region);
1262
+ },
1263
+ defaultMessage(args) {
1264
+ return `invalid parameter ($property).`;
1265
+ }
1266
+ }
1267
+ });
1268
+ };
1269
+ }
1270
+ /**
1271
+ * Checks if the string is an url.
1272
+ *
1273
+ * @export
1274
+ * @param {IsURLOptions} [options]
1275
+ * @param {ValidationOptions} [validationOptions]
1276
+ * @returns {PropertyDecorator}
1277
+ */
1278
+ function IsUrl(options, validationOptions) {
1279
+ return function (object, propertyName) {
1280
+ setExpose(object, propertyName);
1281
+ registerDecorator({
1282
+ name: "vIsUrl",
1283
+ target: object.constructor,
1284
+ propertyName,
1285
+ options: validationOptions,
1286
+ validator: {
1287
+ validate(value, args) {
1288
+ return isURL(value, options);
1289
+ },
1290
+ defaultMessage(args) {
1291
+ return `invalid parameter ($property).`;
1292
+ }
1293
+ }
1294
+ });
1295
+ };
1296
+ }
1297
+ /**
1298
+ * check if the string is a hash of type algorithm. Algorithm is one of ['md4', 'md5', 'sha1', 'sha256',
1299
+ * 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', 'tiger160', 'tiger192', 'crc32', 'crc32b']
1300
+ *
1301
+ * @export
1302
+ * @param {HashAlgorithm} algorithm
1303
+ * @param {ValidationOptions} [validationOptions]
1304
+ * @returns {PropertyDecorator}
1305
+ */
1306
+ function IsHash(algorithm, validationOptions) {
1307
+ return function (object, propertyName) {
1308
+ setExpose(object, propertyName);
1309
+ registerDecorator({
1310
+ name: "vIsHash",
1311
+ target: object.constructor,
1312
+ propertyName,
1313
+ options: validationOptions,
1314
+ validator: {
1315
+ validate(value, args) {
1316
+ return isHash(value, algorithm);
1317
+ },
1318
+ defaultMessage(args) {
1319
+ return `invalid parameter, ($property) must be is an ${algorithm} Hash string.`;
1320
+ }
1321
+ }
1322
+ });
1323
+ };
1324
+ }
1325
+
1326
+ export { ClassValidator, Contains, ENABLE_VALIDATED, Equals, Expose, FunctionValidator, Gt, Gte, IsCnName, IsDate, IsDefined, IsEmail, IsHash, IsIP, IsIdNumber, IsIn, IsMobile, IsNotEmpty, IsNotIn, IsPhoneNumber, IsPlateNumber, IsUrl, IsZipCode, Length, Lt, Lte, NotEquals, PARAM_CHECK_KEY, PARAM_RULE_KEY, PARAM_TYPE_KEY, Valid, Validated, checkParamsType, convertDtoParamsType, convertParamsType, paramterTypes, plainToClass };