koatty_validation 1.3.6 → 1.4.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 CHANGED
@@ -1,1423 +1,15 @@
1
1
  /*!
2
2
  * @Author: richen
3
- * @Date: 2024-11-06 10:51:17
3
+ * @Date: 2025-06-10 23:32:27
4
4
  * @License: BSD (3-Clause)
5
5
  * @Copyright (c) - <richenlin(at)gmail.com>
6
6
  * @HomePage: https://koatty.org/
7
7
  */
8
- import { validate, isEmail, isIP, isPhoneNumber, isURL, isHash, equals, notEquals, contains, isIn, isNotIn, registerDecorator, isDate, length } from 'class-validator';
9
8
  import * as helper from 'koatty_lib';
10
- import { getOriginMetadata, IOCContainer } from 'koatty_container';
11
-
12
- var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
13
-
14
- var _Reflect = {};
15
-
16
- /*! *****************************************************************************
17
- Copyright (C) Microsoft. All rights reserved.
18
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use
19
- this file except in compliance with the License. You may obtain a copy of the
20
- License at http://www.apache.org/licenses/LICENSE-2.0
21
-
22
- THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
23
- KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
24
- WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
25
- MERCHANTABLITY OR NON-INFRINGEMENT.
26
-
27
- See the Apache Version 2.0 License for specific language governing permissions
28
- and limitations under the License.
29
- ***************************************************************************** */
30
-
31
- var hasRequired_Reflect;
32
-
33
- function require_Reflect () {
34
- if (hasRequired_Reflect) return _Reflect;
35
- hasRequired_Reflect = 1;
36
- var Reflect;
37
- (function (Reflect) {
38
- // Metadata Proposal
39
- // https://rbuckton.github.io/reflect-metadata/
40
- (function (factory) {
41
- var root = typeof globalThis === "object" ? globalThis :
42
- typeof commonjsGlobal === "object" ? commonjsGlobal :
43
- typeof self === "object" ? self :
44
- typeof this === "object" ? this :
45
- sloppyModeThis();
46
- var exporter = makeExporter(Reflect);
47
- if (typeof root.Reflect !== "undefined") {
48
- exporter = makeExporter(root.Reflect, exporter);
49
- }
50
- factory(exporter, root);
51
- if (typeof root.Reflect === "undefined") {
52
- root.Reflect = Reflect;
53
- }
54
- function makeExporter(target, previous) {
55
- return function (key, value) {
56
- Object.defineProperty(target, key, { configurable: true, writable: true, value: value });
57
- if (previous)
58
- previous(key, value);
59
- };
60
- }
61
- function functionThis() {
62
- try {
63
- return Function("return this;")();
64
- }
65
- catch (_) { }
66
- }
67
- function indirectEvalThis() {
68
- try {
69
- return (void 0, eval)("(function() { return this; })()");
70
- }
71
- catch (_) { }
72
- }
73
- function sloppyModeThis() {
74
- return functionThis() || indirectEvalThis();
75
- }
76
- })(function (exporter, root) {
77
- var hasOwn = Object.prototype.hasOwnProperty;
78
- // feature test for Symbol support
79
- var supportsSymbol = typeof Symbol === "function";
80
- var toPrimitiveSymbol = supportsSymbol && typeof Symbol.toPrimitive !== "undefined" ? Symbol.toPrimitive : "@@toPrimitive";
81
- var iteratorSymbol = supportsSymbol && typeof Symbol.iterator !== "undefined" ? Symbol.iterator : "@@iterator";
82
- var supportsCreate = typeof Object.create === "function"; // feature test for Object.create support
83
- var supportsProto = { __proto__: [] } instanceof Array; // feature test for __proto__ support
84
- var downLevel = !supportsCreate && !supportsProto;
85
- var HashMap = {
86
- // create an object in dictionary mode (a.k.a. "slow" mode in v8)
87
- create: supportsCreate
88
- ? function () { return MakeDictionary(Object.create(null)); }
89
- : supportsProto
90
- ? function () { return MakeDictionary({ __proto__: null }); }
91
- : function () { return MakeDictionary({}); },
92
- has: downLevel
93
- ? function (map, key) { return hasOwn.call(map, key); }
94
- : function (map, key) { return key in map; },
95
- get: downLevel
96
- ? function (map, key) { return hasOwn.call(map, key) ? map[key] : undefined; }
97
- : function (map, key) { return map[key]; },
98
- };
99
- // Load global or shim versions of Map, Set, and WeakMap
100
- var functionPrototype = Object.getPrototypeOf(Function);
101
- var _Map = typeof Map === "function" && typeof Map.prototype.entries === "function" ? Map : CreateMapPolyfill();
102
- var _Set = typeof Set === "function" && typeof Set.prototype.entries === "function" ? Set : CreateSetPolyfill();
103
- var _WeakMap = typeof WeakMap === "function" ? WeakMap : CreateWeakMapPolyfill();
104
- var registrySymbol = supportsSymbol ? Symbol.for("@reflect-metadata:registry") : undefined;
105
- var metadataRegistry = GetOrCreateMetadataRegistry();
106
- var metadataProvider = CreateMetadataProvider(metadataRegistry);
107
- /**
108
- * Applies a set of decorators to a property of a target object.
109
- * @param decorators An array of decorators.
110
- * @param target The target object.
111
- * @param propertyKey (Optional) The property key to decorate.
112
- * @param attributes (Optional) The property descriptor for the target key.
113
- * @remarks Decorators are applied in reverse order.
114
- * @example
115
- *
116
- * class Example {
117
- * // property declarations are not part of ES6, though they are valid in TypeScript:
118
- * // static staticProperty;
119
- * // property;
120
- *
121
- * constructor(p) { }
122
- * static staticMethod(p) { }
123
- * method(p) { }
124
- * }
125
- *
126
- * // constructor
127
- * Example = Reflect.decorate(decoratorsArray, Example);
128
- *
129
- * // property (on constructor)
130
- * Reflect.decorate(decoratorsArray, Example, "staticProperty");
131
- *
132
- * // property (on prototype)
133
- * Reflect.decorate(decoratorsArray, Example.prototype, "property");
134
- *
135
- * // method (on constructor)
136
- * Object.defineProperty(Example, "staticMethod",
137
- * Reflect.decorate(decoratorsArray, Example, "staticMethod",
138
- * Object.getOwnPropertyDescriptor(Example, "staticMethod")));
139
- *
140
- * // method (on prototype)
141
- * Object.defineProperty(Example.prototype, "method",
142
- * Reflect.decorate(decoratorsArray, Example.prototype, "method",
143
- * Object.getOwnPropertyDescriptor(Example.prototype, "method")));
144
- *
145
- */
146
- function decorate(decorators, target, propertyKey, attributes) {
147
- if (!IsUndefined(propertyKey)) {
148
- if (!IsArray(decorators))
149
- throw new TypeError();
150
- if (!IsObject(target))
151
- throw new TypeError();
152
- if (!IsObject(attributes) && !IsUndefined(attributes) && !IsNull(attributes))
153
- throw new TypeError();
154
- if (IsNull(attributes))
155
- attributes = undefined;
156
- propertyKey = ToPropertyKey(propertyKey);
157
- return DecorateProperty(decorators, target, propertyKey, attributes);
158
- }
159
- else {
160
- if (!IsArray(decorators))
161
- throw new TypeError();
162
- if (!IsConstructor(target))
163
- throw new TypeError();
164
- return DecorateConstructor(decorators, target);
165
- }
166
- }
167
- exporter("decorate", decorate);
168
- // 4.1.2 Reflect.metadata(metadataKey, metadataValue)
169
- // https://rbuckton.github.io/reflect-metadata/#reflect.metadata
170
- /**
171
- * A default metadata decorator factory that can be used on a class, class member, or parameter.
172
- * @param metadataKey The key for the metadata entry.
173
- * @param metadataValue The value for the metadata entry.
174
- * @returns A decorator function.
175
- * @remarks
176
- * If `metadataKey` is already defined for the target and target key, the
177
- * metadataValue for that key will be overwritten.
178
- * @example
179
- *
180
- * // constructor
181
- * @Reflect.metadata(key, value)
182
- * class Example {
183
- * }
184
- *
185
- * // property (on constructor, TypeScript only)
186
- * class Example {
187
- * @Reflect.metadata(key, value)
188
- * static staticProperty;
189
- * }
190
- *
191
- * // property (on prototype, TypeScript only)
192
- * class Example {
193
- * @Reflect.metadata(key, value)
194
- * property;
195
- * }
196
- *
197
- * // method (on constructor)
198
- * class Example {
199
- * @Reflect.metadata(key, value)
200
- * static staticMethod() { }
201
- * }
202
- *
203
- * // method (on prototype)
204
- * class Example {
205
- * @Reflect.metadata(key, value)
206
- * method() { }
207
- * }
208
- *
209
- */
210
- function metadata(metadataKey, metadataValue) {
211
- function decorator(target, propertyKey) {
212
- if (!IsObject(target))
213
- throw new TypeError();
214
- if (!IsUndefined(propertyKey) && !IsPropertyKey(propertyKey))
215
- throw new TypeError();
216
- OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey);
217
- }
218
- return decorator;
219
- }
220
- exporter("metadata", metadata);
221
- /**
222
- * Define a unique metadata entry on the target.
223
- * @param metadataKey A key used to store and retrieve metadata.
224
- * @param metadataValue A value that contains attached metadata.
225
- * @param target The target object on which to define metadata.
226
- * @param propertyKey (Optional) The property key for the target.
227
- * @example
228
- *
229
- * class Example {
230
- * // property declarations are not part of ES6, though they are valid in TypeScript:
231
- * // static staticProperty;
232
- * // property;
233
- *
234
- * constructor(p) { }
235
- * static staticMethod(p) { }
236
- * method(p) { }
237
- * }
238
- *
239
- * // constructor
240
- * Reflect.defineMetadata("custom:annotation", options, Example);
241
- *
242
- * // property (on constructor)
243
- * Reflect.defineMetadata("custom:annotation", options, Example, "staticProperty");
244
- *
245
- * // property (on prototype)
246
- * Reflect.defineMetadata("custom:annotation", options, Example.prototype, "property");
247
- *
248
- * // method (on constructor)
249
- * Reflect.defineMetadata("custom:annotation", options, Example, "staticMethod");
250
- *
251
- * // method (on prototype)
252
- * Reflect.defineMetadata("custom:annotation", options, Example.prototype, "method");
253
- *
254
- * // decorator factory as metadata-producing annotation.
255
- * function MyAnnotation(options): Decorator {
256
- * return (target, key?) => Reflect.defineMetadata("custom:annotation", options, target, key);
257
- * }
258
- *
259
- */
260
- function defineMetadata(metadataKey, metadataValue, target, propertyKey) {
261
- if (!IsObject(target))
262
- throw new TypeError();
263
- if (!IsUndefined(propertyKey))
264
- propertyKey = ToPropertyKey(propertyKey);
265
- return OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey);
266
- }
267
- exporter("defineMetadata", defineMetadata);
268
- /**
269
- * Gets a value indicating whether the target object or its prototype chain has the provided metadata key defined.
270
- * @param metadataKey A key used to store and retrieve metadata.
271
- * @param target The target object on which the metadata is defined.
272
- * @param propertyKey (Optional) The property key for the target.
273
- * @returns `true` if the metadata key was defined on the target object or its prototype chain; otherwise, `false`.
274
- * @example
275
- *
276
- * class Example {
277
- * // property declarations are not part of ES6, though they are valid in TypeScript:
278
- * // static staticProperty;
279
- * // property;
280
- *
281
- * constructor(p) { }
282
- * static staticMethod(p) { }
283
- * method(p) { }
284
- * }
285
- *
286
- * // constructor
287
- * result = Reflect.hasMetadata("custom:annotation", Example);
288
- *
289
- * // property (on constructor)
290
- * result = Reflect.hasMetadata("custom:annotation", Example, "staticProperty");
291
- *
292
- * // property (on prototype)
293
- * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "property");
294
- *
295
- * // method (on constructor)
296
- * result = Reflect.hasMetadata("custom:annotation", Example, "staticMethod");
297
- *
298
- * // method (on prototype)
299
- * result = Reflect.hasMetadata("custom:annotation", Example.prototype, "method");
300
- *
301
- */
302
- function hasMetadata(metadataKey, target, propertyKey) {
303
- if (!IsObject(target))
304
- throw new TypeError();
305
- if (!IsUndefined(propertyKey))
306
- propertyKey = ToPropertyKey(propertyKey);
307
- return OrdinaryHasMetadata(metadataKey, target, propertyKey);
308
- }
309
- exporter("hasMetadata", hasMetadata);
310
- /**
311
- * Gets a value indicating whether the target object has the provided metadata key defined.
312
- * @param metadataKey A key used to store and retrieve metadata.
313
- * @param target The target object on which the metadata is defined.
314
- * @param propertyKey (Optional) The property key for the target.
315
- * @returns `true` if the metadata key was defined on the target object; otherwise, `false`.
316
- * @example
317
- *
318
- * class Example {
319
- * // property declarations are not part of ES6, though they are valid in TypeScript:
320
- * // static staticProperty;
321
- * // property;
322
- *
323
- * constructor(p) { }
324
- * static staticMethod(p) { }
325
- * method(p) { }
326
- * }
327
- *
328
- * // constructor
329
- * result = Reflect.hasOwnMetadata("custom:annotation", Example);
330
- *
331
- * // property (on constructor)
332
- * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticProperty");
333
- *
334
- * // property (on prototype)
335
- * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "property");
336
- *
337
- * // method (on constructor)
338
- * result = Reflect.hasOwnMetadata("custom:annotation", Example, "staticMethod");
339
- *
340
- * // method (on prototype)
341
- * result = Reflect.hasOwnMetadata("custom:annotation", Example.prototype, "method");
342
- *
343
- */
344
- function hasOwnMetadata(metadataKey, target, propertyKey) {
345
- if (!IsObject(target))
346
- throw new TypeError();
347
- if (!IsUndefined(propertyKey))
348
- propertyKey = ToPropertyKey(propertyKey);
349
- return OrdinaryHasOwnMetadata(metadataKey, target, propertyKey);
350
- }
351
- exporter("hasOwnMetadata", hasOwnMetadata);
352
- /**
353
- * Gets the metadata value for the provided metadata key on the target object or its prototype chain.
354
- * @param metadataKey A key used to store and retrieve metadata.
355
- * @param target The target object on which the metadata is defined.
356
- * @param propertyKey (Optional) The property key for the target.
357
- * @returns The metadata value for the metadata key if found; otherwise, `undefined`.
358
- * @example
359
- *
360
- * class Example {
361
- * // property declarations are not part of ES6, though they are valid in TypeScript:
362
- * // static staticProperty;
363
- * // property;
364
- *
365
- * constructor(p) { }
366
- * static staticMethod(p) { }
367
- * method(p) { }
368
- * }
369
- *
370
- * // constructor
371
- * result = Reflect.getMetadata("custom:annotation", Example);
372
- *
373
- * // property (on constructor)
374
- * result = Reflect.getMetadata("custom:annotation", Example, "staticProperty");
375
- *
376
- * // property (on prototype)
377
- * result = Reflect.getMetadata("custom:annotation", Example.prototype, "property");
378
- *
379
- * // method (on constructor)
380
- * result = Reflect.getMetadata("custom:annotation", Example, "staticMethod");
381
- *
382
- * // method (on prototype)
383
- * result = Reflect.getMetadata("custom:annotation", Example.prototype, "method");
384
- *
385
- */
386
- function getMetadata(metadataKey, target, propertyKey) {
387
- if (!IsObject(target))
388
- throw new TypeError();
389
- if (!IsUndefined(propertyKey))
390
- propertyKey = ToPropertyKey(propertyKey);
391
- return OrdinaryGetMetadata(metadataKey, target, propertyKey);
392
- }
393
- exporter("getMetadata", getMetadata);
394
- /**
395
- * Gets the metadata value for the provided metadata key on the target object.
396
- * @param metadataKey A key used to store and retrieve metadata.
397
- * @param target The target object on which the metadata is defined.
398
- * @param propertyKey (Optional) The property key for the target.
399
- * @returns The metadata value for the metadata key if found; otherwise, `undefined`.
400
- * @example
401
- *
402
- * class Example {
403
- * // property declarations are not part of ES6, though they are valid in TypeScript:
404
- * // static staticProperty;
405
- * // property;
406
- *
407
- * constructor(p) { }
408
- * static staticMethod(p) { }
409
- * method(p) { }
410
- * }
411
- *
412
- * // constructor
413
- * result = Reflect.getOwnMetadata("custom:annotation", Example);
414
- *
415
- * // property (on constructor)
416
- * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticProperty");
417
- *
418
- * // property (on prototype)
419
- * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "property");
420
- *
421
- * // method (on constructor)
422
- * result = Reflect.getOwnMetadata("custom:annotation", Example, "staticMethod");
423
- *
424
- * // method (on prototype)
425
- * result = Reflect.getOwnMetadata("custom:annotation", Example.prototype, "method");
426
- *
427
- */
428
- function getOwnMetadata(metadataKey, target, propertyKey) {
429
- if (!IsObject(target))
430
- throw new TypeError();
431
- if (!IsUndefined(propertyKey))
432
- propertyKey = ToPropertyKey(propertyKey);
433
- return OrdinaryGetOwnMetadata(metadataKey, target, propertyKey);
434
- }
435
- exporter("getOwnMetadata", getOwnMetadata);
436
- /**
437
- * Gets the metadata keys defined on the target object or its prototype chain.
438
- * @param target The target object on which the metadata is defined.
439
- * @param propertyKey (Optional) The property key for the target.
440
- * @returns An array of unique metadata keys.
441
- * @example
442
- *
443
- * class Example {
444
- * // property declarations are not part of ES6, though they are valid in TypeScript:
445
- * // static staticProperty;
446
- * // property;
447
- *
448
- * constructor(p) { }
449
- * static staticMethod(p) { }
450
- * method(p) { }
451
- * }
452
- *
453
- * // constructor
454
- * result = Reflect.getMetadataKeys(Example);
455
- *
456
- * // property (on constructor)
457
- * result = Reflect.getMetadataKeys(Example, "staticProperty");
458
- *
459
- * // property (on prototype)
460
- * result = Reflect.getMetadataKeys(Example.prototype, "property");
461
- *
462
- * // method (on constructor)
463
- * result = Reflect.getMetadataKeys(Example, "staticMethod");
464
- *
465
- * // method (on prototype)
466
- * result = Reflect.getMetadataKeys(Example.prototype, "method");
467
- *
468
- */
469
- function getMetadataKeys(target, propertyKey) {
470
- if (!IsObject(target))
471
- throw new TypeError();
472
- if (!IsUndefined(propertyKey))
473
- propertyKey = ToPropertyKey(propertyKey);
474
- return OrdinaryMetadataKeys(target, propertyKey);
475
- }
476
- exporter("getMetadataKeys", getMetadataKeys);
477
- /**
478
- * Gets the unique metadata keys defined on the target object.
479
- * @param target The target object on which the metadata is defined.
480
- * @param propertyKey (Optional) The property key for the target.
481
- * @returns An array of unique metadata keys.
482
- * @example
483
- *
484
- * class Example {
485
- * // property declarations are not part of ES6, though they are valid in TypeScript:
486
- * // static staticProperty;
487
- * // property;
488
- *
489
- * constructor(p) { }
490
- * static staticMethod(p) { }
491
- * method(p) { }
492
- * }
493
- *
494
- * // constructor
495
- * result = Reflect.getOwnMetadataKeys(Example);
496
- *
497
- * // property (on constructor)
498
- * result = Reflect.getOwnMetadataKeys(Example, "staticProperty");
499
- *
500
- * // property (on prototype)
501
- * result = Reflect.getOwnMetadataKeys(Example.prototype, "property");
502
- *
503
- * // method (on constructor)
504
- * result = Reflect.getOwnMetadataKeys(Example, "staticMethod");
505
- *
506
- * // method (on prototype)
507
- * result = Reflect.getOwnMetadataKeys(Example.prototype, "method");
508
- *
509
- */
510
- function getOwnMetadataKeys(target, propertyKey) {
511
- if (!IsObject(target))
512
- throw new TypeError();
513
- if (!IsUndefined(propertyKey))
514
- propertyKey = ToPropertyKey(propertyKey);
515
- return OrdinaryOwnMetadataKeys(target, propertyKey);
516
- }
517
- exporter("getOwnMetadataKeys", getOwnMetadataKeys);
518
- /**
519
- * Deletes the metadata entry from the target object with the provided key.
520
- * @param metadataKey A key used to store and retrieve metadata.
521
- * @param target The target object on which the metadata is defined.
522
- * @param propertyKey (Optional) The property key for the target.
523
- * @returns `true` if the metadata entry was found and deleted; otherwise, false.
524
- * @example
525
- *
526
- * class Example {
527
- * // property declarations are not part of ES6, though they are valid in TypeScript:
528
- * // static staticProperty;
529
- * // property;
530
- *
531
- * constructor(p) { }
532
- * static staticMethod(p) { }
533
- * method(p) { }
534
- * }
535
- *
536
- * // constructor
537
- * result = Reflect.deleteMetadata("custom:annotation", Example);
538
- *
539
- * // property (on constructor)
540
- * result = Reflect.deleteMetadata("custom:annotation", Example, "staticProperty");
541
- *
542
- * // property (on prototype)
543
- * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "property");
544
- *
545
- * // method (on constructor)
546
- * result = Reflect.deleteMetadata("custom:annotation", Example, "staticMethod");
547
- *
548
- * // method (on prototype)
549
- * result = Reflect.deleteMetadata("custom:annotation", Example.prototype, "method");
550
- *
551
- */
552
- function deleteMetadata(metadataKey, target, propertyKey) {
553
- if (!IsObject(target))
554
- throw new TypeError();
555
- if (!IsUndefined(propertyKey))
556
- propertyKey = ToPropertyKey(propertyKey);
557
- if (!IsObject(target))
558
- throw new TypeError();
559
- if (!IsUndefined(propertyKey))
560
- propertyKey = ToPropertyKey(propertyKey);
561
- var provider = GetMetadataProvider(target, propertyKey, /*Create*/ false);
562
- if (IsUndefined(provider))
563
- return false;
564
- return provider.OrdinaryDeleteMetadata(metadataKey, target, propertyKey);
565
- }
566
- exporter("deleteMetadata", deleteMetadata);
567
- function DecorateConstructor(decorators, target) {
568
- for (var i = decorators.length - 1; i >= 0; --i) {
569
- var decorator = decorators[i];
570
- var decorated = decorator(target);
571
- if (!IsUndefined(decorated) && !IsNull(decorated)) {
572
- if (!IsConstructor(decorated))
573
- throw new TypeError();
574
- target = decorated;
575
- }
576
- }
577
- return target;
578
- }
579
- function DecorateProperty(decorators, target, propertyKey, descriptor) {
580
- for (var i = decorators.length - 1; i >= 0; --i) {
581
- var decorator = decorators[i];
582
- var decorated = decorator(target, propertyKey, descriptor);
583
- if (!IsUndefined(decorated) && !IsNull(decorated)) {
584
- if (!IsObject(decorated))
585
- throw new TypeError();
586
- descriptor = decorated;
587
- }
588
- }
589
- return descriptor;
590
- }
591
- // 3.1.1.1 OrdinaryHasMetadata(MetadataKey, O, P)
592
- // https://rbuckton.github.io/reflect-metadata/#ordinaryhasmetadata
593
- function OrdinaryHasMetadata(MetadataKey, O, P) {
594
- var hasOwn = OrdinaryHasOwnMetadata(MetadataKey, O, P);
595
- if (hasOwn)
596
- return true;
597
- var parent = OrdinaryGetPrototypeOf(O);
598
- if (!IsNull(parent))
599
- return OrdinaryHasMetadata(MetadataKey, parent, P);
600
- return false;
601
- }
602
- // 3.1.2.1 OrdinaryHasOwnMetadata(MetadataKey, O, P)
603
- // https://rbuckton.github.io/reflect-metadata/#ordinaryhasownmetadata
604
- function OrdinaryHasOwnMetadata(MetadataKey, O, P) {
605
- var provider = GetMetadataProvider(O, P, /*Create*/ false);
606
- if (IsUndefined(provider))
607
- return false;
608
- return ToBoolean(provider.OrdinaryHasOwnMetadata(MetadataKey, O, P));
609
- }
610
- // 3.1.3.1 OrdinaryGetMetadata(MetadataKey, O, P)
611
- // https://rbuckton.github.io/reflect-metadata/#ordinarygetmetadata
612
- function OrdinaryGetMetadata(MetadataKey, O, P) {
613
- var hasOwn = OrdinaryHasOwnMetadata(MetadataKey, O, P);
614
- if (hasOwn)
615
- return OrdinaryGetOwnMetadata(MetadataKey, O, P);
616
- var parent = OrdinaryGetPrototypeOf(O);
617
- if (!IsNull(parent))
618
- return OrdinaryGetMetadata(MetadataKey, parent, P);
619
- return undefined;
620
- }
621
- // 3.1.4.1 OrdinaryGetOwnMetadata(MetadataKey, O, P)
622
- // https://rbuckton.github.io/reflect-metadata/#ordinarygetownmetadata
623
- function OrdinaryGetOwnMetadata(MetadataKey, O, P) {
624
- var provider = GetMetadataProvider(O, P, /*Create*/ false);
625
- if (IsUndefined(provider))
626
- return;
627
- return provider.OrdinaryGetOwnMetadata(MetadataKey, O, P);
628
- }
629
- // 3.1.5.1 OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P)
630
- // https://rbuckton.github.io/reflect-metadata/#ordinarydefineownmetadata
631
- function OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) {
632
- var provider = GetMetadataProvider(O, P, /*Create*/ true);
633
- provider.OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P);
634
- }
635
- // 3.1.6.1 OrdinaryMetadataKeys(O, P)
636
- // https://rbuckton.github.io/reflect-metadata/#ordinarymetadatakeys
637
- function OrdinaryMetadataKeys(O, P) {
638
- var ownKeys = OrdinaryOwnMetadataKeys(O, P);
639
- var parent = OrdinaryGetPrototypeOf(O);
640
- if (parent === null)
641
- return ownKeys;
642
- var parentKeys = OrdinaryMetadataKeys(parent, P);
643
- if (parentKeys.length <= 0)
644
- return ownKeys;
645
- if (ownKeys.length <= 0)
646
- return parentKeys;
647
- var set = new _Set();
648
- var keys = [];
649
- for (var _i = 0, ownKeys_1 = ownKeys; _i < ownKeys_1.length; _i++) {
650
- var key = ownKeys_1[_i];
651
- var hasKey = set.has(key);
652
- if (!hasKey) {
653
- set.add(key);
654
- keys.push(key);
655
- }
656
- }
657
- for (var _a = 0, parentKeys_1 = parentKeys; _a < parentKeys_1.length; _a++) {
658
- var key = parentKeys_1[_a];
659
- var hasKey = set.has(key);
660
- if (!hasKey) {
661
- set.add(key);
662
- keys.push(key);
663
- }
664
- }
665
- return keys;
666
- }
667
- // 3.1.7.1 OrdinaryOwnMetadataKeys(O, P)
668
- // https://rbuckton.github.io/reflect-metadata/#ordinaryownmetadatakeys
669
- function OrdinaryOwnMetadataKeys(O, P) {
670
- var provider = GetMetadataProvider(O, P, /*create*/ false);
671
- if (!provider) {
672
- return [];
673
- }
674
- return provider.OrdinaryOwnMetadataKeys(O, P);
675
- }
676
- // 6 ECMAScript Data Typ0es and Values
677
- // https://tc39.github.io/ecma262/#sec-ecmascript-data-types-and-values
678
- function Type(x) {
679
- if (x === null)
680
- return 1 /* Null */;
681
- switch (typeof x) {
682
- case "undefined": return 0 /* Undefined */;
683
- case "boolean": return 2 /* Boolean */;
684
- case "string": return 3 /* String */;
685
- case "symbol": return 4 /* Symbol */;
686
- case "number": return 5 /* Number */;
687
- case "object": return x === null ? 1 /* Null */ : 6 /* Object */;
688
- default: return 6 /* Object */;
689
- }
690
- }
691
- // 6.1.1 The Undefined Type
692
- // https://tc39.github.io/ecma262/#sec-ecmascript-language-types-undefined-type
693
- function IsUndefined(x) {
694
- return x === undefined;
695
- }
696
- // 6.1.2 The Null Type
697
- // https://tc39.github.io/ecma262/#sec-ecmascript-language-types-null-type
698
- function IsNull(x) {
699
- return x === null;
700
- }
701
- // 6.1.5 The Symbol Type
702
- // https://tc39.github.io/ecma262/#sec-ecmascript-language-types-symbol-type
703
- function IsSymbol(x) {
704
- return typeof x === "symbol";
705
- }
706
- // 6.1.7 The Object Type
707
- // https://tc39.github.io/ecma262/#sec-object-type
708
- function IsObject(x) {
709
- return typeof x === "object" ? x !== null : typeof x === "function";
710
- }
711
- // 7.1 Type Conversion
712
- // https://tc39.github.io/ecma262/#sec-type-conversion
713
- // 7.1.1 ToPrimitive(input [, PreferredType])
714
- // https://tc39.github.io/ecma262/#sec-toprimitive
715
- function ToPrimitive(input, PreferredType) {
716
- switch (Type(input)) {
717
- case 0 /* Undefined */: return input;
718
- case 1 /* Null */: return input;
719
- case 2 /* Boolean */: return input;
720
- case 3 /* String */: return input;
721
- case 4 /* Symbol */: return input;
722
- case 5 /* Number */: return input;
723
- }
724
- var hint = "string" ;
725
- var exoticToPrim = GetMethod(input, toPrimitiveSymbol);
726
- if (exoticToPrim !== undefined) {
727
- var result = exoticToPrim.call(input, hint);
728
- if (IsObject(result))
729
- throw new TypeError();
730
- return result;
731
- }
732
- return OrdinaryToPrimitive(input);
733
- }
734
- // 7.1.1.1 OrdinaryToPrimitive(O, hint)
735
- // https://tc39.github.io/ecma262/#sec-ordinarytoprimitive
736
- function OrdinaryToPrimitive(O, hint) {
737
- var valueOf, result; {
738
- var toString_1 = O.toString;
739
- if (IsCallable(toString_1)) {
740
- var result = toString_1.call(O);
741
- if (!IsObject(result))
742
- return result;
743
- }
744
- var valueOf = O.valueOf;
745
- if (IsCallable(valueOf)) {
746
- var result = valueOf.call(O);
747
- if (!IsObject(result))
748
- return result;
749
- }
750
- }
751
- throw new TypeError();
752
- }
753
- // 7.1.2 ToBoolean(argument)
754
- // https://tc39.github.io/ecma262/2016/#sec-toboolean
755
- function ToBoolean(argument) {
756
- return !!argument;
757
- }
758
- // 7.1.12 ToString(argument)
759
- // https://tc39.github.io/ecma262/#sec-tostring
760
- function ToString(argument) {
761
- return "" + argument;
762
- }
763
- // 7.1.14 ToPropertyKey(argument)
764
- // https://tc39.github.io/ecma262/#sec-topropertykey
765
- function ToPropertyKey(argument) {
766
- var key = ToPrimitive(argument);
767
- if (IsSymbol(key))
768
- return key;
769
- return ToString(key);
770
- }
771
- // 7.2 Testing and Comparison Operations
772
- // https://tc39.github.io/ecma262/#sec-testing-and-comparison-operations
773
- // 7.2.2 IsArray(argument)
774
- // https://tc39.github.io/ecma262/#sec-isarray
775
- function IsArray(argument) {
776
- return Array.isArray
777
- ? Array.isArray(argument)
778
- : argument instanceof Object
779
- ? argument instanceof Array
780
- : Object.prototype.toString.call(argument) === "[object Array]";
781
- }
782
- // 7.2.3 IsCallable(argument)
783
- // https://tc39.github.io/ecma262/#sec-iscallable
784
- function IsCallable(argument) {
785
- // NOTE: This is an approximation as we cannot check for [[Call]] internal method.
786
- return typeof argument === "function";
787
- }
788
- // 7.2.4 IsConstructor(argument)
789
- // https://tc39.github.io/ecma262/#sec-isconstructor
790
- function IsConstructor(argument) {
791
- // NOTE: This is an approximation as we cannot check for [[Construct]] internal method.
792
- return typeof argument === "function";
793
- }
794
- // 7.2.7 IsPropertyKey(argument)
795
- // https://tc39.github.io/ecma262/#sec-ispropertykey
796
- function IsPropertyKey(argument) {
797
- switch (Type(argument)) {
798
- case 3 /* String */: return true;
799
- case 4 /* Symbol */: return true;
800
- default: return false;
801
- }
802
- }
803
- function SameValueZero(x, y) {
804
- return x === y || x !== x && y !== y;
805
- }
806
- // 7.3 Operations on Objects
807
- // https://tc39.github.io/ecma262/#sec-operations-on-objects
808
- // 7.3.9 GetMethod(V, P)
809
- // https://tc39.github.io/ecma262/#sec-getmethod
810
- function GetMethod(V, P) {
811
- var func = V[P];
812
- if (func === undefined || func === null)
813
- return undefined;
814
- if (!IsCallable(func))
815
- throw new TypeError();
816
- return func;
817
- }
818
- // 7.4 Operations on Iterator Objects
819
- // https://tc39.github.io/ecma262/#sec-operations-on-iterator-objects
820
- function GetIterator(obj) {
821
- var method = GetMethod(obj, iteratorSymbol);
822
- if (!IsCallable(method))
823
- throw new TypeError(); // from Call
824
- var iterator = method.call(obj);
825
- if (!IsObject(iterator))
826
- throw new TypeError();
827
- return iterator;
828
- }
829
- // 7.4.4 IteratorValue(iterResult)
830
- // https://tc39.github.io/ecma262/2016/#sec-iteratorvalue
831
- function IteratorValue(iterResult) {
832
- return iterResult.value;
833
- }
834
- // 7.4.5 IteratorStep(iterator)
835
- // https://tc39.github.io/ecma262/#sec-iteratorstep
836
- function IteratorStep(iterator) {
837
- var result = iterator.next();
838
- return result.done ? false : result;
839
- }
840
- // 7.4.6 IteratorClose(iterator, completion)
841
- // https://tc39.github.io/ecma262/#sec-iteratorclose
842
- function IteratorClose(iterator) {
843
- var f = iterator["return"];
844
- if (f)
845
- f.call(iterator);
846
- }
847
- // 9.1 Ordinary Object Internal Methods and Internal Slots
848
- // https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots
849
- // 9.1.1.1 OrdinaryGetPrototypeOf(O)
850
- // https://tc39.github.io/ecma262/#sec-ordinarygetprototypeof
851
- function OrdinaryGetPrototypeOf(O) {
852
- var proto = Object.getPrototypeOf(O);
853
- if (typeof O !== "function" || O === functionPrototype)
854
- return proto;
855
- // TypeScript doesn't set __proto__ in ES5, as it's non-standard.
856
- // Try to determine the superclass constructor. Compatible implementations
857
- // must either set __proto__ on a subclass constructor to the superclass constructor,
858
- // or ensure each class has a valid `constructor` property on its prototype that
859
- // points back to the constructor.
860
- // If this is not the same as Function.[[Prototype]], then this is definately inherited.
861
- // This is the case when in ES6 or when using __proto__ in a compatible browser.
862
- if (proto !== functionPrototype)
863
- return proto;
864
- // If the super prototype is Object.prototype, null, or undefined, then we cannot determine the heritage.
865
- var prototype = O.prototype;
866
- var prototypeProto = prototype && Object.getPrototypeOf(prototype);
867
- if (prototypeProto == null || prototypeProto === Object.prototype)
868
- return proto;
869
- // If the constructor was not a function, then we cannot determine the heritage.
870
- var constructor = prototypeProto.constructor;
871
- if (typeof constructor !== "function")
872
- return proto;
873
- // If we have some kind of self-reference, then we cannot determine the heritage.
874
- if (constructor === O)
875
- return proto;
876
- // we have a pretty good guess at the heritage.
877
- return constructor;
878
- }
879
- // Global metadata registry
880
- // - Allows `import "reflect-metadata"` and `import "reflect-metadata/no-conflict"` to interoperate.
881
- // - Uses isolated metadata if `Reflect` is frozen before the registry can be installed.
882
- /**
883
- * Creates a registry used to allow multiple `reflect-metadata` providers.
884
- */
885
- function CreateMetadataRegistry() {
886
- var fallback;
887
- if (!IsUndefined(registrySymbol) &&
888
- typeof root.Reflect !== "undefined" &&
889
- !(registrySymbol in root.Reflect) &&
890
- typeof root.Reflect.defineMetadata === "function") {
891
- // interoperate with older version of `reflect-metadata` that did not support a registry.
892
- fallback = CreateFallbackProvider(root.Reflect);
893
- }
894
- var first;
895
- var second;
896
- var rest;
897
- var targetProviderMap = new _WeakMap();
898
- var registry = {
899
- registerProvider: registerProvider,
900
- getProvider: getProvider,
901
- setProvider: setProvider,
902
- };
903
- return registry;
904
- function registerProvider(provider) {
905
- if (!Object.isExtensible(registry)) {
906
- throw new Error("Cannot add provider to a frozen registry.");
907
- }
908
- switch (true) {
909
- case fallback === provider: break;
910
- case IsUndefined(first):
911
- first = provider;
912
- break;
913
- case first === provider: break;
914
- case IsUndefined(second):
915
- second = provider;
916
- break;
917
- case second === provider: break;
918
- default:
919
- if (rest === undefined)
920
- rest = new _Set();
921
- rest.add(provider);
922
- break;
923
- }
924
- }
925
- function getProviderNoCache(O, P) {
926
- if (!IsUndefined(first)) {
927
- if (first.isProviderFor(O, P))
928
- return first;
929
- if (!IsUndefined(second)) {
930
- if (second.isProviderFor(O, P))
931
- return first;
932
- if (!IsUndefined(rest)) {
933
- var iterator = GetIterator(rest);
934
- while (true) {
935
- var next = IteratorStep(iterator);
936
- if (!next) {
937
- return undefined;
938
- }
939
- var provider = IteratorValue(next);
940
- if (provider.isProviderFor(O, P)) {
941
- IteratorClose(iterator);
942
- return provider;
943
- }
944
- }
945
- }
946
- }
947
- }
948
- if (!IsUndefined(fallback) && fallback.isProviderFor(O, P)) {
949
- return fallback;
950
- }
951
- return undefined;
952
- }
953
- function getProvider(O, P) {
954
- var providerMap = targetProviderMap.get(O);
955
- var provider;
956
- if (!IsUndefined(providerMap)) {
957
- provider = providerMap.get(P);
958
- }
959
- if (!IsUndefined(provider)) {
960
- return provider;
961
- }
962
- provider = getProviderNoCache(O, P);
963
- if (!IsUndefined(provider)) {
964
- if (IsUndefined(providerMap)) {
965
- providerMap = new _Map();
966
- targetProviderMap.set(O, providerMap);
967
- }
968
- providerMap.set(P, provider);
969
- }
970
- return provider;
971
- }
972
- function hasProvider(provider) {
973
- if (IsUndefined(provider))
974
- throw new TypeError();
975
- return first === provider || second === provider || !IsUndefined(rest) && rest.has(provider);
976
- }
977
- function setProvider(O, P, provider) {
978
- if (!hasProvider(provider)) {
979
- throw new Error("Metadata provider not registered.");
980
- }
981
- var existingProvider = getProvider(O, P);
982
- if (existingProvider !== provider) {
983
- if (!IsUndefined(existingProvider)) {
984
- return false;
985
- }
986
- var providerMap = targetProviderMap.get(O);
987
- if (IsUndefined(providerMap)) {
988
- providerMap = new _Map();
989
- targetProviderMap.set(O, providerMap);
990
- }
991
- providerMap.set(P, provider);
992
- }
993
- return true;
994
- }
995
- }
996
- /**
997
- * Gets or creates the shared registry of metadata providers.
998
- */
999
- function GetOrCreateMetadataRegistry() {
1000
- var metadataRegistry;
1001
- if (!IsUndefined(registrySymbol) && IsObject(root.Reflect) && Object.isExtensible(root.Reflect)) {
1002
- metadataRegistry = root.Reflect[registrySymbol];
1003
- }
1004
- if (IsUndefined(metadataRegistry)) {
1005
- metadataRegistry = CreateMetadataRegistry();
1006
- }
1007
- if (!IsUndefined(registrySymbol) && IsObject(root.Reflect) && Object.isExtensible(root.Reflect)) {
1008
- Object.defineProperty(root.Reflect, registrySymbol, {
1009
- enumerable: false,
1010
- configurable: false,
1011
- writable: false,
1012
- value: metadataRegistry
1013
- });
1014
- }
1015
- return metadataRegistry;
1016
- }
1017
- function CreateMetadataProvider(registry) {
1018
- // [[Metadata]] internal slot
1019
- // https://rbuckton.github.io/reflect-metadata/#ordinary-object-internal-methods-and-internal-slots
1020
- var metadata = new _WeakMap();
1021
- var provider = {
1022
- isProviderFor: function (O, P) {
1023
- var targetMetadata = metadata.get(O);
1024
- if (IsUndefined(targetMetadata))
1025
- return false;
1026
- return targetMetadata.has(P);
1027
- },
1028
- OrdinaryDefineOwnMetadata: OrdinaryDefineOwnMetadata,
1029
- OrdinaryHasOwnMetadata: OrdinaryHasOwnMetadata,
1030
- OrdinaryGetOwnMetadata: OrdinaryGetOwnMetadata,
1031
- OrdinaryOwnMetadataKeys: OrdinaryOwnMetadataKeys,
1032
- OrdinaryDeleteMetadata: OrdinaryDeleteMetadata,
1033
- };
1034
- metadataRegistry.registerProvider(provider);
1035
- return provider;
1036
- function GetOrCreateMetadataMap(O, P, Create) {
1037
- var targetMetadata = metadata.get(O);
1038
- var createdTargetMetadata = false;
1039
- if (IsUndefined(targetMetadata)) {
1040
- if (!Create)
1041
- return undefined;
1042
- targetMetadata = new _Map();
1043
- metadata.set(O, targetMetadata);
1044
- createdTargetMetadata = true;
1045
- }
1046
- var metadataMap = targetMetadata.get(P);
1047
- if (IsUndefined(metadataMap)) {
1048
- if (!Create)
1049
- return undefined;
1050
- metadataMap = new _Map();
1051
- targetMetadata.set(P, metadataMap);
1052
- if (!registry.setProvider(O, P, provider)) {
1053
- targetMetadata.delete(P);
1054
- if (createdTargetMetadata) {
1055
- metadata.delete(O);
1056
- }
1057
- throw new Error("Wrong provider for target.");
1058
- }
1059
- }
1060
- return metadataMap;
1061
- }
1062
- // 3.1.2.1 OrdinaryHasOwnMetadata(MetadataKey, O, P)
1063
- // https://rbuckton.github.io/reflect-metadata/#ordinaryhasownmetadata
1064
- function OrdinaryHasOwnMetadata(MetadataKey, O, P) {
1065
- var metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false);
1066
- if (IsUndefined(metadataMap))
1067
- return false;
1068
- return ToBoolean(metadataMap.has(MetadataKey));
1069
- }
1070
- // 3.1.4.1 OrdinaryGetOwnMetadata(MetadataKey, O, P)
1071
- // https://rbuckton.github.io/reflect-metadata/#ordinarygetownmetadata
1072
- function OrdinaryGetOwnMetadata(MetadataKey, O, P) {
1073
- var metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false);
1074
- if (IsUndefined(metadataMap))
1075
- return undefined;
1076
- return metadataMap.get(MetadataKey);
1077
- }
1078
- // 3.1.5.1 OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P)
1079
- // https://rbuckton.github.io/reflect-metadata/#ordinarydefineownmetadata
1080
- function OrdinaryDefineOwnMetadata(MetadataKey, MetadataValue, O, P) {
1081
- var metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ true);
1082
- metadataMap.set(MetadataKey, MetadataValue);
1083
- }
1084
- // 3.1.7.1 OrdinaryOwnMetadataKeys(O, P)
1085
- // https://rbuckton.github.io/reflect-metadata/#ordinaryownmetadatakeys
1086
- function OrdinaryOwnMetadataKeys(O, P) {
1087
- var keys = [];
1088
- var metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false);
1089
- if (IsUndefined(metadataMap))
1090
- return keys;
1091
- var keysObj = metadataMap.keys();
1092
- var iterator = GetIterator(keysObj);
1093
- var k = 0;
1094
- while (true) {
1095
- var next = IteratorStep(iterator);
1096
- if (!next) {
1097
- keys.length = k;
1098
- return keys;
1099
- }
1100
- var nextValue = IteratorValue(next);
1101
- try {
1102
- keys[k] = nextValue;
1103
- }
1104
- catch (e) {
1105
- try {
1106
- IteratorClose(iterator);
1107
- }
1108
- finally {
1109
- throw e;
1110
- }
1111
- }
1112
- k++;
1113
- }
1114
- }
1115
- function OrdinaryDeleteMetadata(MetadataKey, O, P) {
1116
- var metadataMap = GetOrCreateMetadataMap(O, P, /*Create*/ false);
1117
- if (IsUndefined(metadataMap))
1118
- return false;
1119
- if (!metadataMap.delete(MetadataKey))
1120
- return false;
1121
- if (metadataMap.size === 0) {
1122
- var targetMetadata = metadata.get(O);
1123
- if (!IsUndefined(targetMetadata)) {
1124
- targetMetadata.delete(P);
1125
- if (targetMetadata.size === 0) {
1126
- metadata.delete(targetMetadata);
1127
- }
1128
- }
1129
- }
1130
- return true;
1131
- }
1132
- }
1133
- function CreateFallbackProvider(reflect) {
1134
- var defineMetadata = reflect.defineMetadata, hasOwnMetadata = reflect.hasOwnMetadata, getOwnMetadata = reflect.getOwnMetadata, getOwnMetadataKeys = reflect.getOwnMetadataKeys, deleteMetadata = reflect.deleteMetadata;
1135
- var metadataOwner = new _WeakMap();
1136
- var provider = {
1137
- isProviderFor: function (O, P) {
1138
- var metadataPropertySet = metadataOwner.get(O);
1139
- if (!IsUndefined(metadataPropertySet)) {
1140
- return metadataPropertySet.has(P);
1141
- }
1142
- if (getOwnMetadataKeys(O, P).length) {
1143
- if (IsUndefined(metadataPropertySet)) {
1144
- metadataPropertySet = new _Set();
1145
- metadataOwner.set(O, metadataPropertySet);
1146
- }
1147
- metadataPropertySet.add(P);
1148
- return true;
1149
- }
1150
- return false;
1151
- },
1152
- OrdinaryDefineOwnMetadata: defineMetadata,
1153
- OrdinaryHasOwnMetadata: hasOwnMetadata,
1154
- OrdinaryGetOwnMetadata: getOwnMetadata,
1155
- OrdinaryOwnMetadataKeys: getOwnMetadataKeys,
1156
- OrdinaryDeleteMetadata: deleteMetadata,
1157
- };
1158
- return provider;
1159
- }
1160
- /**
1161
- * Gets the metadata provider for an object. If the object has no metadata provider and this is for a create operation,
1162
- * then this module's metadata provider is assigned to the object.
1163
- */
1164
- function GetMetadataProvider(O, P, Create) {
1165
- var registeredProvider = metadataRegistry.getProvider(O, P);
1166
- if (!IsUndefined(registeredProvider)) {
1167
- return registeredProvider;
1168
- }
1169
- if (Create) {
1170
- if (metadataRegistry.setProvider(O, P, metadataProvider)) {
1171
- return metadataProvider;
1172
- }
1173
- throw new Error("Illegal state.");
1174
- }
1175
- return undefined;
1176
- }
1177
- // naive Map shim
1178
- function CreateMapPolyfill() {
1179
- var cacheSentinel = {};
1180
- var arraySentinel = [];
1181
- var MapIterator = /** @class */ (function () {
1182
- function MapIterator(keys, values, selector) {
1183
- this._index = 0;
1184
- this._keys = keys;
1185
- this._values = values;
1186
- this._selector = selector;
1187
- }
1188
- MapIterator.prototype["@@iterator"] = function () { return this; };
1189
- MapIterator.prototype[iteratorSymbol] = function () { return this; };
1190
- MapIterator.prototype.next = function () {
1191
- var index = this._index;
1192
- if (index >= 0 && index < this._keys.length) {
1193
- var result = this._selector(this._keys[index], this._values[index]);
1194
- if (index + 1 >= this._keys.length) {
1195
- this._index = -1;
1196
- this._keys = arraySentinel;
1197
- this._values = arraySentinel;
1198
- }
1199
- else {
1200
- this._index++;
1201
- }
1202
- return { value: result, done: false };
1203
- }
1204
- return { value: undefined, done: true };
1205
- };
1206
- MapIterator.prototype.throw = function (error) {
1207
- if (this._index >= 0) {
1208
- this._index = -1;
1209
- this._keys = arraySentinel;
1210
- this._values = arraySentinel;
1211
- }
1212
- throw error;
1213
- };
1214
- MapIterator.prototype.return = function (value) {
1215
- if (this._index >= 0) {
1216
- this._index = -1;
1217
- this._keys = arraySentinel;
1218
- this._values = arraySentinel;
1219
- }
1220
- return { value: value, done: true };
1221
- };
1222
- return MapIterator;
1223
- }());
1224
- var Map = /** @class */ (function () {
1225
- function Map() {
1226
- this._keys = [];
1227
- this._values = [];
1228
- this._cacheKey = cacheSentinel;
1229
- this._cacheIndex = -2;
1230
- }
1231
- Object.defineProperty(Map.prototype, "size", {
1232
- get: function () { return this._keys.length; },
1233
- enumerable: true,
1234
- configurable: true
1235
- });
1236
- Map.prototype.has = function (key) { return this._find(key, /*insert*/ false) >= 0; };
1237
- Map.prototype.get = function (key) {
1238
- var index = this._find(key, /*insert*/ false);
1239
- return index >= 0 ? this._values[index] : undefined;
1240
- };
1241
- Map.prototype.set = function (key, value) {
1242
- var index = this._find(key, /*insert*/ true);
1243
- this._values[index] = value;
1244
- return this;
1245
- };
1246
- Map.prototype.delete = function (key) {
1247
- var index = this._find(key, /*insert*/ false);
1248
- if (index >= 0) {
1249
- var size = this._keys.length;
1250
- for (var i = index + 1; i < size; i++) {
1251
- this._keys[i - 1] = this._keys[i];
1252
- this._values[i - 1] = this._values[i];
1253
- }
1254
- this._keys.length--;
1255
- this._values.length--;
1256
- if (SameValueZero(key, this._cacheKey)) {
1257
- this._cacheKey = cacheSentinel;
1258
- this._cacheIndex = -2;
1259
- }
1260
- return true;
1261
- }
1262
- return false;
1263
- };
1264
- Map.prototype.clear = function () {
1265
- this._keys.length = 0;
1266
- this._values.length = 0;
1267
- this._cacheKey = cacheSentinel;
1268
- this._cacheIndex = -2;
1269
- };
1270
- Map.prototype.keys = function () { return new MapIterator(this._keys, this._values, getKey); };
1271
- Map.prototype.values = function () { return new MapIterator(this._keys, this._values, getValue); };
1272
- Map.prototype.entries = function () { return new MapIterator(this._keys, this._values, getEntry); };
1273
- Map.prototype["@@iterator"] = function () { return this.entries(); };
1274
- Map.prototype[iteratorSymbol] = function () { return this.entries(); };
1275
- Map.prototype._find = function (key, insert) {
1276
- if (!SameValueZero(this._cacheKey, key)) {
1277
- this._cacheIndex = -1;
1278
- for (var i = 0; i < this._keys.length; i++) {
1279
- if (SameValueZero(this._keys[i], key)) {
1280
- this._cacheIndex = i;
1281
- break;
1282
- }
1283
- }
1284
- }
1285
- if (this._cacheIndex < 0 && insert) {
1286
- this._cacheIndex = this._keys.length;
1287
- this._keys.push(key);
1288
- this._values.push(undefined);
1289
- }
1290
- return this._cacheIndex;
1291
- };
1292
- return Map;
1293
- }());
1294
- return Map;
1295
- function getKey(key, _) {
1296
- return key;
1297
- }
1298
- function getValue(_, value) {
1299
- return value;
1300
- }
1301
- function getEntry(key, value) {
1302
- return [key, value];
1303
- }
1304
- }
1305
- // naive Set shim
1306
- function CreateSetPolyfill() {
1307
- var Set = /** @class */ (function () {
1308
- function Set() {
1309
- this._map = new _Map();
1310
- }
1311
- Object.defineProperty(Set.prototype, "size", {
1312
- get: function () { return this._map.size; },
1313
- enumerable: true,
1314
- configurable: true
1315
- });
1316
- Set.prototype.has = function (value) { return this._map.has(value); };
1317
- Set.prototype.add = function (value) { return this._map.set(value, value), this; };
1318
- Set.prototype.delete = function (value) { return this._map.delete(value); };
1319
- Set.prototype.clear = function () { this._map.clear(); };
1320
- Set.prototype.keys = function () { return this._map.keys(); };
1321
- Set.prototype.values = function () { return this._map.keys(); };
1322
- Set.prototype.entries = function () { return this._map.entries(); };
1323
- Set.prototype["@@iterator"] = function () { return this.keys(); };
1324
- Set.prototype[iteratorSymbol] = function () { return this.keys(); };
1325
- return Set;
1326
- }());
1327
- return Set;
1328
- }
1329
- // naive WeakMap shim
1330
- function CreateWeakMapPolyfill() {
1331
- var UUID_SIZE = 16;
1332
- var keys = HashMap.create();
1333
- var rootKey = CreateUniqueKey();
1334
- return /** @class */ (function () {
1335
- function WeakMap() {
1336
- this._key = CreateUniqueKey();
1337
- }
1338
- WeakMap.prototype.has = function (target) {
1339
- var table = GetOrCreateWeakMapTable(target, /*create*/ false);
1340
- return table !== undefined ? HashMap.has(table, this._key) : false;
1341
- };
1342
- WeakMap.prototype.get = function (target) {
1343
- var table = GetOrCreateWeakMapTable(target, /*create*/ false);
1344
- return table !== undefined ? HashMap.get(table, this._key) : undefined;
1345
- };
1346
- WeakMap.prototype.set = function (target, value) {
1347
- var table = GetOrCreateWeakMapTable(target, /*create*/ true);
1348
- table[this._key] = value;
1349
- return this;
1350
- };
1351
- WeakMap.prototype.delete = function (target) {
1352
- var table = GetOrCreateWeakMapTable(target, /*create*/ false);
1353
- return table !== undefined ? delete table[this._key] : false;
1354
- };
1355
- WeakMap.prototype.clear = function () {
1356
- // NOTE: not a real clear, just makes the previous data unreachable
1357
- this._key = CreateUniqueKey();
1358
- };
1359
- return WeakMap;
1360
- }());
1361
- function CreateUniqueKey() {
1362
- var key;
1363
- do
1364
- key = "@@WeakMap@@" + CreateUUID();
1365
- while (HashMap.has(keys, key));
1366
- keys[key] = true;
1367
- return key;
1368
- }
1369
- function GetOrCreateWeakMapTable(target, create) {
1370
- if (!hasOwn.call(target, rootKey)) {
1371
- if (!create)
1372
- return undefined;
1373
- Object.defineProperty(target, rootKey, { value: HashMap.create() });
1374
- }
1375
- return target[rootKey];
1376
- }
1377
- function FillRandomBytes(buffer, size) {
1378
- for (var i = 0; i < size; ++i)
1379
- buffer[i] = Math.random() * 0xff | 0;
1380
- return buffer;
1381
- }
1382
- function GenRandomBytes(size) {
1383
- if (typeof Uint8Array === "function") {
1384
- if (typeof crypto !== "undefined")
1385
- return crypto.getRandomValues(new Uint8Array(size));
1386
- if (typeof msCrypto !== "undefined")
1387
- return msCrypto.getRandomValues(new Uint8Array(size));
1388
- return FillRandomBytes(new Uint8Array(size), size);
1389
- }
1390
- return FillRandomBytes(new Array(size), size);
1391
- }
1392
- function CreateUUID() {
1393
- var data = GenRandomBytes(UUID_SIZE);
1394
- // mark as random - RFC 4122 § 4.4
1395
- data[6] = data[6] & 0x4f | 0x40;
1396
- data[8] = data[8] & 0xbf | 0x80;
1397
- var result = "";
1398
- for (var offset = 0; offset < UUID_SIZE; ++offset) {
1399
- var byte = data[offset];
1400
- if (offset === 4 || offset === 6 || offset === 8)
1401
- result += "-";
1402
- if (byte < 16)
1403
- result += "0";
1404
- result += byte.toString(16).toLowerCase();
1405
- }
1406
- return result;
1407
- }
1408
- }
1409
- // uses a heuristic used by v8 and chakra to force an object into dictionary mode.
1410
- function MakeDictionary(obj) {
1411
- obj.__ = undefined;
1412
- delete obj.__;
1413
- return obj;
1414
- }
1415
- });
1416
- })(Reflect || (Reflect = {}));
1417
- return _Reflect;
1418
- }
1419
-
1420
- require_Reflect();
9
+ import 'reflect-metadata';
10
+ import { getOriginMetadata } from 'koatty_container';
11
+ import { validate, isNotIn, isIn, contains, notEquals, equals, isHash, isURL, isPhoneNumber, isIP, isEmail, registerDecorator } from 'class-validator';
12
+ import { LRUCache } from 'lru-cache';
1421
13
 
1422
14
  /**
1423
15
  * @ author: richen
@@ -1426,6 +18,8 @@ require_Reflect();
1426
18
  * @ version: 2020-03-20 11:34:38
1427
19
  */
1428
20
  // tslint:disable-next-line: no-import-side-effect
21
+ // 参数类型键常量
22
+ const PARAM_TYPE_KEY = 'PARAM_TYPE_KEY';
1429
23
  /**
1430
24
  * Set property as included in the process of transformation.
1431
25
  *
@@ -1594,7 +188,7 @@ function convertParamsType(param, type) {
1594
188
  }
1595
189
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1596
190
  }
1597
- catch (err) {
191
+ catch (_err) {
1598
192
  return param;
1599
193
  }
1600
194
  }
@@ -1742,10 +336,9 @@ function plateNumber(value) {
1742
336
  * @Usage:
1743
337
  * @Author: richen
1744
338
  * @Date: 2021-11-25 10:47:04
1745
- * @LastEditTime: 2024-10-31 16:57:28
339
+ * @LastEditTime: 2024-01-03 14:32:49
1746
340
  */
1747
341
  // constant
1748
- const PARAM_TYPE_KEY = 'PARAM_TYPE_KEY';
1749
342
  const PARAM_RULE_KEY = 'PARAM_RULE_KEY';
1750
343
  const PARAM_CHECK_KEY = 'PARAM_CHECK_KEY';
1751
344
  const ENABLE_VALIDATED = "ENABLE_VALIDATED";
@@ -1779,7 +372,6 @@ var paramterTypes;
1779
372
  paramterTypes[paramterTypes["undefined"] = 19] = "undefined";
1780
373
  })(paramterTypes || (paramterTypes = {}));
1781
374
  class ValidateClass {
1782
- static instance;
1783
375
  constructor() {
1784
376
  }
1785
377
  /**
@@ -1802,10 +394,20 @@ class ValidateClass {
1802
394
  * @memberof ValidateClass
1803
395
  */
1804
396
  async valid(Clazz, data, convert = false) {
1805
- const obj = data instanceof Clazz ? data : plainToClass(Clazz, data, convert);
1806
- const errors = convert
1807
- ? await validate(obj)
1808
- : await validate(obj, { skipMissingProperties: true });
397
+ let obj = {};
398
+ if (data instanceof Clazz) {
399
+ obj = data;
400
+ }
401
+ else {
402
+ obj = plainToClass(Clazz, data, convert);
403
+ }
404
+ let errors = [];
405
+ if (convert) {
406
+ errors = await validate(obj);
407
+ }
408
+ else {
409
+ errors = await validate(obj, { skipMissingProperties: true });
410
+ }
1809
411
  if (errors.length > 0) {
1810
412
  throw new Error(Object.values(errors[0].constraints)[0]);
1811
413
  }
@@ -1978,743 +580,850 @@ const ValidFuncs = {
1978
580
  * @param {(string | ValidOtpions)} [options]
1979
581
  * @returns {*}
1980
582
  */
1981
- const FunctionValidator = {};
583
+ /* eslint-disable @typescript-eslint/no-unused-vars */
584
+ const FunctionValidator = {
585
+ IsNotEmpty: function (_value, _options) {
586
+ throw new Error("Function not implemented.");
587
+ },
588
+ IsDate: function (_value, _options) {
589
+ throw new Error("Function not implemented.");
590
+ },
591
+ IsEmail: function (_value, _options) {
592
+ throw new Error("Function not implemented.");
593
+ },
594
+ IsIP: function (_value, _options) {
595
+ throw new Error("Function not implemented.");
596
+ },
597
+ IsPhoneNumber: function (_value, _options) {
598
+ throw new Error("Function not implemented.");
599
+ },
600
+ IsUrl: function (_value, _options) {
601
+ throw new Error("Function not implemented.");
602
+ },
603
+ IsHash: function (_value, _options) {
604
+ throw new Error("Function not implemented.");
605
+ },
606
+ IsCnName: function (_value, _options) {
607
+ throw new Error("Function not implemented.");
608
+ },
609
+ IsIdNumber: function (_value, _options) {
610
+ throw new Error("Function not implemented.");
611
+ },
612
+ IsZipCode: function (_value, _options) {
613
+ throw new Error("Function not implemented.");
614
+ },
615
+ IsMobile: function (_value, _options) {
616
+ throw new Error("Function not implemented.");
617
+ },
618
+ IsPlateNumber: function (_value, _options) {
619
+ throw new Error("Function not implemented.");
620
+ },
621
+ Equals: function (_value, _options) {
622
+ throw new Error("Function not implemented.");
623
+ },
624
+ NotEquals: function (_value, _options) {
625
+ throw new Error("Function not implemented.");
626
+ },
627
+ Contains: function (_value, _options) {
628
+ throw new Error("Function not implemented.");
629
+ },
630
+ IsIn: function (_value, _options) {
631
+ throw new Error("Function not implemented.");
632
+ },
633
+ IsNotIn: function (_value, _options) {
634
+ throw new Error("Function not implemented.");
635
+ },
636
+ Gt: function (_value, _options) {
637
+ throw new Error("Function not implemented.");
638
+ },
639
+ Lt: function (_value, _options) {
640
+ throw new Error("Function not implemented.");
641
+ },
642
+ Gte: function (_value, _options) {
643
+ throw new Error("Function not implemented.");
644
+ },
645
+ Lte: function (_value, _options) {
646
+ throw new Error("Function not implemented.");
647
+ }
648
+ };
649
+ /* eslint-enable @typescript-eslint/no-unused-vars */
1982
650
  Object.keys(ValidFuncs).forEach((key) => {
1983
651
  FunctionValidator[key] = (value, options) => {
1984
- if (helper.isString(options)) {
1985
- options = { message: options, value: null };
652
+ let validOptions;
653
+ if (typeof options === 'string') {
654
+ validOptions = { message: options, value: null };
1986
655
  }
1987
- if (!ValidFuncs[key](value, options.value)) {
1988
- throw new Error(options.message || `ValidatorError: invalid arguments.`);
656
+ else {
657
+ validOptions = options || { message: `ValidatorError: invalid arguments.`, value: null };
658
+ }
659
+ if (!ValidFuncs[key](value, validOptions.value)) {
660
+ throw new Error(validOptions.message || `ValidatorError: invalid arguments.`);
1989
661
  }
1990
662
  };
1991
663
  });
1992
664
 
1993
- /*
1994
- * @Description:
1995
- * @Usage:
1996
- * @Author: richen
1997
- * @Date: 2021-11-25 10:46:57
1998
- * @LastEditTime: 2024-10-31 16:49:26
1999
- */
2000
665
  /**
2001
- * Validation parameter's type and values.
2002
- *
2003
- * @export
2004
- * @param {(ValidRules | ValidRules[] | Function)} rule
2005
- * @param {*} [options] If the options type is a string, the value is the error message of the validation rule.
2006
- * Some validation rules require additional parameters, ext: @Valid("Gte", {message:"Requires value greater than or equal to 100", value: 100})
2007
- * @returns {*} {ParameterDecorator}
666
+ * 装饰器工厂 - 消除装饰器代码重复
667
+ * @author richen
2008
668
  */
2009
- function Valid(rule, options) {
2010
- let rules = [];
2011
- if (helper.isString(rule)) {
2012
- rules = rule.split(",");
2013
- }
2014
- else {
2015
- rules = rule;
2016
- }
2017
- return (target, propertyKey, descriptor) => {
2018
- // 获取成员参数类型
2019
- const paramTypes = Reflect.getMetadata("design:paramtypes", target, propertyKey);
2020
- const type = (paramTypes[descriptor]?.name) ? paramTypes[descriptor].name : 'object';
2021
- if (helper.isString(options)) {
2022
- options = { message: options, value: null };
2023
- }
2024
- IOCContainer.attachPropertyData(PARAM_RULE_KEY, {
2025
- name: propertyKey,
2026
- rule: rules,
2027
- options,
2028
- index: descriptor,
2029
- type
2030
- }, target, propertyKey);
2031
- };
2032
- }
2033
669
  /**
2034
- * Validation parameter's type and values from DTO class.
2035
- *
2036
- * @export
2037
- * @returns {MethodDecorator}
670
+ * 创建验证装饰器的工厂函数
671
+ * @param options 装饰器配置选项
672
+ * @returns 装饰器工厂函数
2038
673
  */
2039
- function Validated() {
2040
- return (target, propertyKey, _descriptor) => {
2041
- //
2042
- IOCContainer.savePropertyData(PARAM_CHECK_KEY, {
2043
- dtoCheck: 1
2044
- }, target, propertyKey);
2045
- // 获取成员参数类型
2046
- // const paramTypes = Reflect.getMetadata("design:paramtypes", target, propertyKey) || [];
2047
- // const { value, configurable, enumerable } = descriptor;
2048
- // descriptor = {
2049
- // configurable,
2050
- // enumerable,
2051
- // writable: true,
2052
- // value: async function valid(...props: any[]) {
2053
- // const ps: any[] = [];
2054
- // // tslint:disable-next-line: no-unused-expression
2055
- // (props || []).map((value: any, index: number) => {
2056
- // const type = (paramTypes[index] && paramTypes[index].name) ? paramTypes[index].name : "any";
2057
- // if (!paramterTypes[type]) {
2058
- // ps.push(ClassValidator.valid(paramTypes[index], value, true));
2059
- // } else {
2060
- // ps.push(Promise.resolve(value));
2061
- // }
2062
- // });
2063
- // if (ps.length > 0) {
2064
- // props = await Promise.all(ps);
2065
- // }
2066
- // // tslint:disable-next-line: no-invalid-this
2067
- // return value.apply(this, props);
2068
- // }
2069
- // };
2070
- // return descriptor;
674
+ function createValidationDecorator(options) {
675
+ const { name, validator, defaultMessage, requiresValue = false } = options;
676
+ return function decoratorFactory(...args) {
677
+ // 处理参数:最后一个参数是ValidationOptions,前面是验证函数的参数
678
+ const validationOptions = args[args.length - 1];
679
+ const validatorArgs = requiresValue ? args.slice(0, -1) : [];
680
+ return function propertyDecorator(object, propertyName) {
681
+ // 设置属性为可导出
682
+ setExpose(object, propertyName);
683
+ // 注册验证装饰器
684
+ registerDecorator({
685
+ name,
686
+ target: object.constructor,
687
+ propertyName,
688
+ options: validationOptions,
689
+ constraints: validatorArgs,
690
+ validator: {
691
+ validate(value) {
692
+ try {
693
+ return validator(value, ...validatorArgs);
694
+ }
695
+ catch {
696
+ return false;
697
+ }
698
+ },
699
+ defaultMessage(validationArguments) {
700
+ const property = validationArguments.property;
701
+ return defaultMessage
702
+ ? defaultMessage.replace('$property', property)
703
+ : `Invalid value for ${property}`;
704
+ }
705
+ }
706
+ });
707
+ };
2071
708
  };
2072
709
  }
2073
710
  /**
2074
- * Marks property as included in the process of transformation.
2075
- *
2076
- * @export
2077
- * @returns {PropertyDecorator}
711
+ * 创建简单验证装饰器(不需要额外参数)
712
+ * @param name 装饰器名称
713
+ * @param validator 验证函数
714
+ * @param defaultMessage 默认错误信息
715
+ * @returns 装饰器函数
2078
716
  */
2079
- function Expose() {
2080
- return function (object, propertyName) {
2081
- setExpose(object, propertyName);
2082
- };
717
+ function createSimpleDecorator(name, validator, defaultMessage) {
718
+ return createValidationDecorator({
719
+ name,
720
+ validator,
721
+ defaultMessage,
722
+ requiresValue: false
723
+ });
2083
724
  }
2084
725
  /**
2085
- * Alias of Expose
2086
- *
2087
- * @export
2088
- * @returns {PropertyDecorator}
726
+ * 创建带参数的验证装饰器
727
+ * @param name 装饰器名称
728
+ * @param validator 验证函数
729
+ * @param defaultMessage 默认错误信息
730
+ * @returns 装饰器工厂函数
2089
731
  */
2090
- function IsDefined() {
2091
- return function (object, propertyName) {
2092
- setExpose(object, propertyName);
2093
- };
732
+ function createParameterizedDecorator(name, validator, defaultMessage) {
733
+ return createValidationDecorator({
734
+ name,
735
+ validator,
736
+ defaultMessage,
737
+ requiresValue: true
738
+ });
2094
739
  }
740
+
2095
741
  /**
2096
- * Checks if value is a chinese name.
2097
- *
2098
- * @export
2099
- * @param {string} property
2100
- * @param {ValidationOptions} [validationOptions]
2101
- * @returns {PropertyDecorator}
742
+ * 重构后的装饰器定义 - 使用工厂函数消除重复
743
+ * @author richen
2102
744
  */
2103
- function IsCnName(validationOptions) {
2104
- return function (object, propertyName) {
2105
- setExpose(object, propertyName);
2106
- registerDecorator({
2107
- name: "IsCnName",
2108
- target: object.constructor,
2109
- propertyName,
2110
- options: validationOptions,
2111
- validator: {
2112
- validate(value, _args) {
2113
- return cnName(value);
2114
- },
2115
- defaultMessage(_args) {
2116
- return "invalid parameter ($property).";
2117
- }
2118
- }
2119
- });
2120
- };
745
+ // 中国本土化验证装饰器
746
+ const IsCnName = createSimpleDecorator('IsCnName', (value) => helper.isString(value) && cnName(value), 'must be a valid Chinese name');
747
+ const IsIdNumber = createSimpleDecorator('IsIdNumber', (value) => helper.isString(value) && idNumber(value), 'must be a valid ID number');
748
+ const IsZipCode = createSimpleDecorator('IsZipCode', (value) => helper.isString(value) && zipCode(value), 'must be a valid zip code');
749
+ const IsMobile = createSimpleDecorator('IsMobile', (value) => helper.isString(value) && mobile(value), 'must be a valid mobile number');
750
+ const IsPlateNumber = createSimpleDecorator('IsPlateNumber', (value) => helper.isString(value) && plateNumber(value), 'must be a valid plate number');
751
+ // 基础验证装饰器
752
+ const IsNotEmpty = createSimpleDecorator('IsNotEmpty', (value) => !helper.isEmpty(value), 'should not be empty');
753
+ const IsDate = createSimpleDecorator('IsDate', (value) => helper.isDate(value), 'must be a valid date');
754
+ // 带参数的验证装饰器
755
+ const Equals = createParameterizedDecorator('Equals', (value, comparison) => value === comparison, 'must equal to $constraint1');
756
+ const NotEquals = createParameterizedDecorator('NotEquals', (value, comparison) => value !== comparison, 'should not equal to $constraint1');
757
+ const Contains = createParameterizedDecorator('Contains', (value, seed) => helper.isString(value) && value.includes(seed), 'must contain $constraint1');
758
+ const IsIn = createParameterizedDecorator('IsIn', (value, possibleValues) => possibleValues.includes(value), 'must be one of the following values: $constraint1');
759
+ const IsNotIn = createParameterizedDecorator('IsNotIn', (value, possibleValues) => !possibleValues.includes(value), 'should not be one of the following values: $constraint1');
760
+ // 数值比较装饰器
761
+ const Gt = createParameterizedDecorator('Gt', (value, min) => helper.toNumber(value) > min, 'must be greater than $constraint1');
762
+ const Gte = createParameterizedDecorator('Gte', (value, min) => helper.toNumber(value) >= min, 'must be greater than or equal to $constraint1');
763
+ const Lt = createParameterizedDecorator('Lt', (value, max) => helper.toNumber(value) < max, 'must be less than $constraint1');
764
+ const Lte = createParameterizedDecorator('Lte', (value, max) => helper.toNumber(value) <= max, 'must be less than or equal to $constraint1');
765
+ // 复杂验证装饰器(需要特殊处理)
766
+ function IsEmail(options, validationOptions) {
767
+ return createParameterizedDecorator('IsEmail', (value) => isEmail(value, options), 'must be a valid email')(validationOptions);
768
+ }
769
+ function IsIP(version, validationOptions) {
770
+ return createParameterizedDecorator('IsIP', (value) => isIP(value, version), 'must be a valid IP address')(validationOptions);
771
+ }
772
+ function IsPhoneNumber(region, validationOptions) {
773
+ return createParameterizedDecorator('IsPhoneNumber', (value) => isPhoneNumber(value, region), 'must be a valid phone number')(validationOptions);
774
+ }
775
+ function IsUrl(options, validationOptions) {
776
+ return createParameterizedDecorator('IsUrl', (value) => isURL(value, options), 'must be a valid URL')(validationOptions);
777
+ }
778
+ function IsHash(algorithm, validationOptions) {
779
+ return createParameterizedDecorator('IsHash', (value) => isHash(value, algorithm), 'must be a valid hash')(validationOptions);
2121
780
  }
781
+ // 基础工具装饰器(从原始decorator.ts移植)
2122
782
  /**
2123
- * Checks if value is a idCard number(chinese).
2124
- *
2125
- * @export
2126
- * @param {string} property
2127
- * @param {ValidationOptions} [validationOptions]
2128
- * @returns {PropertyDecorator}
783
+ * 标记属性为可导出
2129
784
  */
2130
- function IsIdNumber(validationOptions) {
785
+ function Expose() {
2131
786
  return function (object, propertyName) {
2132
787
  setExpose(object, propertyName);
2133
- registerDecorator({
2134
- name: "IsIdNumber",
2135
- target: object.constructor,
2136
- propertyName,
2137
- options: validationOptions,
2138
- validator: {
2139
- validate(value, _args) {
2140
- return idNumber(value);
2141
- },
2142
- defaultMessage(_args) {
2143
- return "invalid parameter ($property).";
2144
- }
2145
- }
2146
- });
2147
788
  };
2148
789
  }
2149
790
  /**
2150
- * Checks if value is a zipCode(chinese).
2151
- *
2152
- * @export
2153
- * @param {string} property
2154
- * @param {ValidationOptions} [validationOptions]
2155
- * @returns {PropertyDecorator}
791
+ * Expose的别名
2156
792
  */
2157
- function IsZipCode(validationOptions) {
793
+ function IsDefined() {
2158
794
  return function (object, propertyName) {
2159
795
  setExpose(object, propertyName);
2160
- registerDecorator({
2161
- name: "IsZipCode",
2162
- target: object.constructor,
2163
- propertyName,
2164
- options: validationOptions,
2165
- validator: {
2166
- validate(value, _args) {
2167
- return zipCode(value);
2168
- },
2169
- defaultMessage(_args) {
2170
- return "invalid parameter ($property).";
2171
- }
2172
- }
2173
- });
2174
796
  };
2175
797
  }
2176
798
  /**
2177
- * Checks if value is a mobile phone number(chinese).
2178
- *
2179
- * @export
2180
- * @param {string} property
2181
- * @param {ValidationOptions} [validationOptions]
2182
- * @returns {PropertyDecorator}
799
+ * 参数验证装饰器
2183
800
  */
2184
- function IsMobile(validationOptions) {
2185
- return function (object, propertyName) {
2186
- setExpose(object, propertyName);
2187
- registerDecorator({
2188
- name: "IsMobile",
2189
- target: object.constructor,
2190
- propertyName,
2191
- options: validationOptions,
2192
- validator: {
2193
- validate(value, _args) {
2194
- return mobile(value);
2195
- },
2196
- defaultMessage(_args) {
2197
- return "invalid parameter ($property).";
2198
- }
2199
- }
2200
- });
801
+ function Valid(rule, options) {
802
+ return function (object, propertyName, parameterIndex) {
803
+ // 这里保持与原始实现一致
804
+ const existingRules = Reflect.getOwnMetadata("validate", object, propertyName) || {};
805
+ existingRules[parameterIndex] = { rule, options };
806
+ Reflect.defineMetadata("validate", existingRules, object, propertyName);
2201
807
  };
2202
808
  }
2203
809
  /**
2204
- * Checks if value is a plate number(chinese).
2205
- *
2206
- * @export
2207
- * @param {string} property
2208
- * @param {ValidationOptions} [validationOptions]
2209
- * @returns {PropertyDecorator}
810
+ * 方法验证装饰器
2210
811
  */
2211
- function IsPlateNumber(validationOptions) {
2212
- return function (object, propertyName) {
2213
- setExpose(object, propertyName);
2214
- registerDecorator({
2215
- name: "IsPlateNumber",
2216
- target: object.constructor,
2217
- propertyName,
2218
- options: validationOptions,
2219
- validator: {
2220
- validate(value, _args) {
2221
- return plateNumber(value);
2222
- },
2223
- defaultMessage(_args) {
2224
- return "invalid parameter ($property).";
2225
- }
2226
- }
2227
- });
812
+ function Validated() {
813
+ return function (object, propertyName, descriptor) {
814
+ const originalMethod = descriptor.value;
815
+ descriptor.value = function (...args) {
816
+ // 这里可以添加验证逻辑
817
+ return originalMethod.apply(this, args);
818
+ };
819
+ return descriptor;
2228
820
  };
2229
821
  }
822
+
2230
823
  /**
2231
- * Checks value is not empty, undefined, null, '', NaN, [], {} and any empty string(including spaces, tabs, formfeeds, etc.), returns false.
2232
- *
2233
- * @export
2234
- * @param {ValidationOptions} [validationOptions]
2235
- * @returns {PropertyDecorator}
824
+ * 改进的错误处理机制
825
+ * @author richen
2236
826
  */
2237
- function IsNotEmpty(validationOptions) {
2238
- return function (object, propertyName) {
2239
- setExpose(object, propertyName);
2240
- registerDecorator({
2241
- name: "IsNotEmpty",
2242
- target: object.constructor,
2243
- propertyName,
2244
- options: validationOptions,
2245
- validator: {
2246
- validate(value, _args) {
2247
- return !helper.isEmpty(value);
2248
- },
2249
- defaultMessage(_args) {
2250
- return "invalid parameter ($property).";
2251
- }
2252
- }
2253
- });
2254
- };
2255
- }
2256
827
  /**
2257
- * Checks if value matches ("===") the comparison.
2258
- *
2259
- * @export
2260
- * @param {*} comparison
2261
- * @param {ValidationOptions} [validationOptions]
2262
- * @returns {PropertyDecorator}
828
+ * 错误信息国际化
2263
829
  */
2264
- function Equals(comparison, validationOptions) {
2265
- return function (object, propertyName) {
2266
- setExpose(object, propertyName);
2267
- registerDecorator({
2268
- name: "vEquals",
2269
- target: object.constructor,
2270
- propertyName,
2271
- options: validationOptions,
2272
- validator: {
2273
- validate(value, _args) {
2274
- return equals(value, comparison);
2275
- },
2276
- defaultMessage(_args) {
2277
- return `invalid parameter, ($property) must be equals ${comparison}.`;
2278
- }
2279
- }
2280
- });
2281
- };
2282
- }
830
+ const ERROR_MESSAGES = {
831
+ zh: {
832
+ // 中国本土化验证
833
+ IsCnName: '必须是有效的中文姓名',
834
+ IsIdNumber: '必须是有效的身份证号码',
835
+ IsZipCode: '必须是有效的邮政编码',
836
+ IsMobile: '必须是有效的手机号码',
837
+ IsPlateNumber: '必须是有效的车牌号码',
838
+ // 基础验证
839
+ IsNotEmpty: '不能为空',
840
+ IsDate: '必须是有效的日期',
841
+ IsEmail: '必须是有效的邮箱地址',
842
+ IsIP: '必须是有效的IP地址',
843
+ IsPhoneNumber: '必须是有效的电话号码',
844
+ IsUrl: '必须是有效的URL地址',
845
+ IsHash: '必须是有效的哈希值',
846
+ // 比较验证
847
+ Equals: '必须等于 {comparison}',
848
+ NotEquals: '不能等于 {comparison}',
849
+ Contains: '必须包含 {seed}',
850
+ IsIn: '必须是以下值之一: {possibleValues}',
851
+ IsNotIn: '不能是以下值之一: {possibleValues}',
852
+ Gt: '必须大于 {min}',
853
+ Gte: '必须大于或等于 {min}',
854
+ Lt: '必须小于 {max}',
855
+ Lte: '必须小于或等于 {max}',
856
+ // 通用错误
857
+ invalidParameter: '参数 {field} 无效',
858
+ validationFailed: '验证失败',
859
+ },
860
+ en: {
861
+ // Chinese localization validators
862
+ IsCnName: 'must be a valid Chinese name',
863
+ IsIdNumber: 'must be a valid ID number',
864
+ IsZipCode: 'must be a valid zip code',
865
+ IsMobile: 'must be a valid mobile number',
866
+ IsPlateNumber: 'must be a valid plate number',
867
+ // Basic validators
868
+ IsNotEmpty: 'should not be empty',
869
+ IsDate: 'must be a valid date',
870
+ IsEmail: 'must be a valid email',
871
+ IsIP: 'must be a valid IP address',
872
+ IsPhoneNumber: 'must be a valid phone number',
873
+ IsUrl: 'must be a valid URL',
874
+ IsHash: 'must be a valid hash',
875
+ // Comparison validators
876
+ Equals: 'must equal to {comparison}',
877
+ NotEquals: 'should not equal to {comparison}',
878
+ Contains: 'must contain {seed}',
879
+ IsIn: 'must be one of the following values: {possibleValues}',
880
+ IsNotIn: 'should not be one of the following values: {possibleValues}',
881
+ Gt: 'must be greater than {min}',
882
+ Gte: 'must be greater than or equal to {min}',
883
+ Lt: 'must be less than {max}',
884
+ Lte: 'must be less than or equal to {max}',
885
+ // Common errors
886
+ invalidParameter: 'invalid parameter {field}',
887
+ validationFailed: 'validation failed',
888
+ }
889
+ };
2283
890
  /**
2284
- * Checks if value does not match ("!==") the comparison.
2285
- *
2286
- * @export
2287
- * @param {*} comparison
2288
- * @param {ValidationOptions} [validationOptions]
2289
- * @returns {PropertyDecorator}
891
+ * 增强的验证错误类
2290
892
  */
2291
- function NotEquals(comparison, validationOptions) {
2292
- return function (object, propertyName) {
2293
- setExpose(object, propertyName);
2294
- registerDecorator({
2295
- name: "vNotEquals",
2296
- target: object.constructor,
2297
- propertyName,
2298
- options: validationOptions,
2299
- validator: {
2300
- validate(value, _args) {
2301
- return notEquals(value, comparison);
2302
- },
2303
- defaultMessage(_args) {
2304
- return `invalid parameter, ($property) must be not equals ${comparison}.`;
2305
- }
2306
- }
2307
- });
2308
- };
893
+ class KoattyValidationError extends Error {
894
+ constructor(errors, message) {
895
+ const errorMessage = message || 'Validation failed';
896
+ super(errorMessage);
897
+ this.name = 'KoattyValidationError';
898
+ this.errors = errors;
899
+ this.statusCode = 400;
900
+ this.timestamp = new Date();
901
+ // 确保正确的原型链
902
+ Object.setPrototypeOf(this, KoattyValidationError.prototype);
903
+ }
904
+ /**
905
+ * 获取第一个错误信息
906
+ */
907
+ getFirstError() {
908
+ return this.errors[0];
909
+ }
910
+ /**
911
+ * 获取指定字段的错误
912
+ */
913
+ getFieldErrors(field) {
914
+ return this.errors.filter(error => error.field === field);
915
+ }
916
+ /**
917
+ * 转换为JSON格式
918
+ */
919
+ toJSON() {
920
+ return {
921
+ name: this.name,
922
+ message: this.message,
923
+ statusCode: this.statusCode,
924
+ timestamp: this.timestamp,
925
+ errors: this.errors
926
+ };
927
+ }
2309
928
  }
2310
929
  /**
2311
- * Checks if the string contains the seed.
2312
- *
2313
- * @export
2314
- * @param {string} seed
2315
- * @param {ValidationOptions} [validationOptions]
2316
- * @returns {PropertyDecorator}
930
+ * 错误信息格式化器
2317
931
  */
2318
- function Contains(seed, validationOptions) {
2319
- return function (object, propertyName) {
2320
- setExpose(object, propertyName);
2321
- registerDecorator({
2322
- name: "vContains",
2323
- target: object.constructor,
2324
- propertyName,
2325
- options: validationOptions,
2326
- validator: {
2327
- validate(value, _args) {
2328
- return contains(value, seed);
2329
- // return typeof value === "string" && (value.indexOf(seed) > -1);
2330
- },
2331
- defaultMessage(_args) {
2332
- return `invalid parameter, ($property) must be contains ${seed}.`;
2333
- }
932
+ class ErrorMessageFormatter {
933
+ constructor(language = 'zh') {
934
+ this.language = 'zh';
935
+ this.language = language;
936
+ }
937
+ /**
938
+ * 设置语言
939
+ */
940
+ setLanguage(language) {
941
+ this.language = language;
942
+ }
943
+ /**
944
+ * 格式化错误消息
945
+ */
946
+ formatMessage(constraint, field, value, context) {
947
+ const messages = ERROR_MESSAGES[this.language];
948
+ let template = messages[constraint] || messages.invalidParameter;
949
+ // 替换占位符
950
+ template = template.replace('{field}', field);
951
+ // 优先使用上下文中的值,然后是传入的value
952
+ if (context) {
953
+ Object.entries(context).forEach(([key, val]) => {
954
+ template = template.replace(`{${key}}`, this.formatValue(val));
955
+ });
956
+ }
957
+ // 如果还有{value}占位符且传入了value,则替换
958
+ if (value !== undefined && template.includes('{value}')) {
959
+ template = template.replace('{value}', this.formatValue(value));
960
+ }
961
+ return template;
962
+ }
963
+ /**
964
+ * 格式化值用于消息显示
965
+ * @private
966
+ */
967
+ formatValue(value) {
968
+ if (value === null)
969
+ return 'null';
970
+ if (value === undefined)
971
+ return 'undefined';
972
+ if (typeof value === 'number')
973
+ return String(value);
974
+ if (typeof value === 'string')
975
+ return `"${value}"`;
976
+ if (Array.isArray(value))
977
+ return `[${value.map(v => this.formatValue(v)).join(', ')}]`;
978
+ if (typeof value === 'object') {
979
+ try {
980
+ return JSON.stringify(value);
2334
981
  }
2335
- });
2336
- };
982
+ catch {
983
+ // 处理循环引用
984
+ return '[Circular Reference]';
985
+ }
986
+ }
987
+ return String(value);
988
+ }
2337
989
  }
2338
990
  /**
2339
- * Checks if given value is in a array of allowed values.
2340
- *
2341
- * @export
2342
- * @param {any[]} possibleValues
2343
- * @param {ValidationOptions} [validationOptions]
2344
- * @returns {PropertyDecorator}
991
+ * 全局错误信息格式化器实例
2345
992
  */
2346
- function IsIn(possibleValues, validationOptions) {
2347
- return function (object, propertyName) {
2348
- setExpose(object, propertyName);
2349
- registerDecorator({
2350
- name: "vIsIn",
2351
- target: object.constructor,
2352
- propertyName,
2353
- options: validationOptions,
2354
- validator: {
2355
- validate(value, _args) {
2356
- return isIn(value, possibleValues);
2357
- },
2358
- defaultMessage(_args) {
2359
- return `invalid parameter ($property).`;
2360
- }
2361
- }
2362
- });
2363
- };
2364
- }
993
+ const errorFormatter = new ErrorMessageFormatter();
2365
994
  /**
2366
- * Checks if given value not in a array of allowed values.
2367
- *
2368
- * @export
2369
- * @param {any[]} possibleValues
2370
- * @param {ValidationOptions} [validationOptions]
2371
- * @returns {PropertyDecorator}
995
+ * 设置全局语言
2372
996
  */
2373
- function IsNotIn(possibleValues, validationOptions) {
2374
- return function (object, propertyName) {
2375
- setExpose(object, propertyName);
2376
- registerDecorator({
2377
- name: "vIsNotIn",
2378
- target: object.constructor,
2379
- propertyName,
2380
- options: validationOptions,
2381
- validator: {
2382
- validate(value, _args) {
2383
- return isNotIn(value, possibleValues);
2384
- },
2385
- defaultMessage(_args) {
2386
- return `invalid parameter ($property).`;
2387
- }
2388
- }
2389
- });
2390
- };
997
+ function setValidationLanguage(language) {
998
+ errorFormatter.setLanguage(language);
2391
999
  }
2392
1000
  /**
2393
- * Checks if a given value is a real date.
2394
- *
2395
- * @export
2396
- * @param {ValidationOptions} [validationOptions]
2397
- * @returns {PropertyDecorator}
1001
+ * 创建验证错误
2398
1002
  */
2399
- function IsDate(validationOptions) {
2400
- return function (object, propertyName) {
2401
- setExpose(object, propertyName);
2402
- registerDecorator({
2403
- name: "vIsDate",
2404
- target: object.constructor,
2405
- propertyName,
2406
- options: validationOptions,
2407
- validator: {
2408
- validate(value, _args) {
2409
- return isDate(value);
2410
- },
2411
- defaultMessage(_args) {
2412
- return `invalid parameter ($property).`;
2413
- }
2414
- }
2415
- });
1003
+ function createValidationError(field, value, constraint, customMessage, context) {
1004
+ const message = customMessage || errorFormatter.formatMessage(constraint, field, value, context);
1005
+ return {
1006
+ field,
1007
+ value,
1008
+ constraint,
1009
+ message,
1010
+ context
2416
1011
  };
2417
1012
  }
2418
1013
  /**
2419
- * Checks if the first number is greater than or equal to the min value.
2420
- *
2421
- * @export
2422
- * @param {number} min
2423
- * @param {ValidationOptions} [validationOptions]
2424
- * @returns {PropertyDecorator}
1014
+ * 批量创建验证错误
2425
1015
  */
2426
- function Gt(min, validationOptions) {
2427
- return function (object, propertyName) {
2428
- setExpose(object, propertyName);
2429
- registerDecorator({
2430
- name: "vMin",
2431
- target: object.constructor,
2432
- propertyName,
2433
- options: validationOptions,
2434
- validator: {
2435
- validate(value, _args) {
2436
- return helper.toNumber(value) > min;
2437
- },
2438
- defaultMessage(_args) {
2439
- return `invalid parameter ($property).`;
2440
- }
2441
- }
2442
- });
2443
- };
1016
+ function createValidationErrors(errors) {
1017
+ const validationErrors = errors.map(error => createValidationError(error.field, error.value, error.constraint, error.message, error.context));
1018
+ return new KoattyValidationError(validationErrors);
2444
1019
  }
1020
+
2445
1021
  /**
2446
- * Checks if the first number is less than or equal to the max value.
2447
- *
2448
- * @export
2449
- * @param {number} max
2450
- * @param {ValidationOptions} [validationOptions]
2451
- * @returns {PropertyDecorator}
1022
+ * 性能缓存模块 - 提供多层次缓存和性能监控
1023
+ * @author richen
2452
1024
  */
2453
- function Lt(max, validationOptions) {
2454
- return function (object, propertyName) {
2455
- setExpose(object, propertyName);
2456
- registerDecorator({
2457
- name: "vMax",
2458
- target: object.constructor,
2459
- propertyName,
2460
- options: validationOptions,
2461
- validator: {
2462
- validate(value, _args) {
2463
- return helper.toNumber(value) < max;
2464
- },
2465
- defaultMessage(_args) {
2466
- return `invalid parameter ($property).`;
2467
- }
2468
- }
2469
- });
2470
- };
2471
- }
2472
1025
  /**
2473
- * Checks if the first number is greater than or equal to the min value.
2474
- *
2475
- * @export
2476
- * @param {number} min
2477
- * @param {ValidationOptions} [validationOptions]
2478
- * @returns {PropertyDecorator}
1026
+ * 元数据缓存
2479
1027
  */
2480
- function Gte(min, validationOptions) {
2481
- return function (object, propertyName) {
2482
- setExpose(object, propertyName);
2483
- registerDecorator({
2484
- name: "vMin",
2485
- target: object.constructor,
2486
- propertyName,
2487
- options: validationOptions,
2488
- validator: {
2489
- validate(value, _args) {
2490
- return helper.toNumber(value) >= min;
2491
- },
2492
- defaultMessage(_args) {
2493
- return `invalid parameter ($property).`;
2494
- }
2495
- }
2496
- });
2497
- };
1028
+ class MetadataCache {
1029
+ constructor() {
1030
+ this.cache = new WeakMap();
1031
+ }
1032
+ static getInstance() {
1033
+ if (!MetadataCache.instance) {
1034
+ MetadataCache.instance = new MetadataCache();
1035
+ }
1036
+ return MetadataCache.instance;
1037
+ }
1038
+ /**
1039
+ * 获取类的元数据缓存
1040
+ */
1041
+ getClassCache(target) {
1042
+ if (!this.cache.has(target)) {
1043
+ this.cache.set(target, new Map());
1044
+ }
1045
+ return this.cache.get(target);
1046
+ }
1047
+ /**
1048
+ * 缓存元数据
1049
+ */
1050
+ setMetadata(target, key, value) {
1051
+ const classCache = this.getClassCache(target);
1052
+ classCache.set(key, value);
1053
+ }
1054
+ /**
1055
+ * 获取缓存的元数据
1056
+ */
1057
+ getMetadata(target, key) {
1058
+ const classCache = this.getClassCache(target);
1059
+ return classCache.get(key);
1060
+ }
1061
+ /**
1062
+ * 检查是否已缓存
1063
+ */
1064
+ hasMetadata(target, key) {
1065
+ const classCache = this.getClassCache(target);
1066
+ return classCache.has(key);
1067
+ }
1068
+ /**
1069
+ * 清空指定类的缓存
1070
+ */
1071
+ clearClassCache(target) {
1072
+ if (this.cache.has(target)) {
1073
+ this.cache.delete(target);
1074
+ }
1075
+ }
2498
1076
  }
2499
1077
  /**
2500
- * Checks if the first number is less than or equal to the max value.
2501
- *
2502
- * @export
2503
- * @param {number} max
2504
- * @param {ValidationOptions} [validationOptions]
2505
- * @returns {PropertyDecorator}
1078
+ * 验证结果缓存
2506
1079
  */
2507
- function Lte(max, validationOptions) {
2508
- return function (object, propertyName) {
2509
- setExpose(object, propertyName);
2510
- registerDecorator({
2511
- name: "vMax",
2512
- target: object.constructor,
2513
- propertyName,
2514
- options: validationOptions,
2515
- validator: {
2516
- validate(value, _args) {
2517
- return helper.toNumber(value) <= max;
2518
- },
2519
- defaultMessage(_args) {
2520
- return `invalid parameter ($property).`;
2521
- }
2522
- }
1080
+ class ValidationCache {
1081
+ constructor(options) {
1082
+ this.cache = new LRUCache({
1083
+ max: (options === null || options === void 0 ? void 0 : options.max) || 5000,
1084
+ ttl: (options === null || options === void 0 ? void 0 : options.ttl) || 1000 * 60 * 10, // 10分钟
1085
+ allowStale: (options === null || options === void 0 ? void 0 : options.allowStale) || false,
1086
+ updateAgeOnGet: (options === null || options === void 0 ? void 0 : options.updateAgeOnGet) || true,
2523
1087
  });
2524
- };
1088
+ }
1089
+ static getInstance(options) {
1090
+ if (!ValidationCache.instance) {
1091
+ ValidationCache.instance = new ValidationCache(options);
1092
+ }
1093
+ return ValidationCache.instance;
1094
+ }
1095
+ /**
1096
+ * 生成缓存键
1097
+ */
1098
+ generateKey(validator, value, ...args) {
1099
+ const valueStr = this.serializeValue(value);
1100
+ const argsStr = args.length > 0 ? JSON.stringify(args) : '';
1101
+ return `${validator}:${valueStr}:${argsStr}`;
1102
+ }
1103
+ /**
1104
+ * 序列化值用于缓存键
1105
+ */
1106
+ serializeValue(value) {
1107
+ if (value === null)
1108
+ return 'null';
1109
+ if (value === undefined)
1110
+ return 'undefined';
1111
+ if (typeof value === 'string')
1112
+ return `s:${value}`;
1113
+ if (typeof value === 'number')
1114
+ return `n:${value}`;
1115
+ if (typeof value === 'boolean')
1116
+ return `b:${value}`;
1117
+ if (Array.isArray(value))
1118
+ return `a:${JSON.stringify(value)}`;
1119
+ if (typeof value === 'object')
1120
+ return `o:${JSON.stringify(value)}`;
1121
+ return String(value);
1122
+ }
1123
+ /**
1124
+ * 获取缓存的验证结果
1125
+ */
1126
+ get(validator, value, ...args) {
1127
+ const key = this.generateKey(validator, value, ...args);
1128
+ return this.cache.get(key);
1129
+ }
1130
+ /**
1131
+ * 缓存验证结果
1132
+ */
1133
+ set(validator, value, result, ...args) {
1134
+ const key = this.generateKey(validator, value, ...args);
1135
+ this.cache.set(key, result);
1136
+ }
1137
+ /**
1138
+ * 检查是否存在缓存
1139
+ */
1140
+ has(validator, value, ...args) {
1141
+ const key = this.generateKey(validator, value, ...args);
1142
+ return this.cache.has(key);
1143
+ }
1144
+ /**
1145
+ * 删除特定缓存
1146
+ */
1147
+ delete(validator, value, ...args) {
1148
+ const key = this.generateKey(validator, value, ...args);
1149
+ return this.cache.delete(key);
1150
+ }
1151
+ /**
1152
+ * 清空缓存
1153
+ */
1154
+ clear() {
1155
+ this.cache.clear();
1156
+ }
1157
+ /**
1158
+ * 获取缓存统计
1159
+ */
1160
+ getStats() {
1161
+ return {
1162
+ size: this.cache.size,
1163
+ max: this.cache.max,
1164
+ calculatedSize: this.cache.calculatedSize,
1165
+ keyCount: this.cache.size,
1166
+ };
1167
+ }
1168
+ /**
1169
+ * 设置缓存TTL
1170
+ */
1171
+ setTTL(validator, value, ttl, ...args) {
1172
+ const key = this.generateKey(validator, value, ...args);
1173
+ const existingValue = this.cache.get(key);
1174
+ if (existingValue !== undefined) {
1175
+ this.cache.set(key, existingValue, { ttl });
1176
+ }
1177
+ }
2525
1178
  }
2526
1179
  /**
2527
- * Checks if the string's length falls in a range. Note: this function takes into account surrogate pairs.
2528
- * If given value is not a string, then it returns false.
2529
- *
2530
- * @export
2531
- * @param {number} min
2532
- * @param {number} [max]
2533
- * @param {ValidationOptions} [validationOptions]
2534
- * @returns {PropertyDecorator}
1180
+ * 正则表达式缓存
2535
1181
  */
2536
- function Length(min, max, validationOptions) {
2537
- return function (object, propertyName) {
2538
- setExpose(object, propertyName);
2539
- registerDecorator({
2540
- name: "vLength",
2541
- target: object.constructor,
2542
- propertyName,
2543
- options: validationOptions,
2544
- validator: {
2545
- validate(value, _args) {
2546
- return length(value, min, max);
2547
- },
2548
- defaultMessage(_args) {
2549
- return `invalid parameter ($property).`;
2550
- }
1182
+ class RegexCache {
1183
+ constructor(options) {
1184
+ this.cache = new LRUCache({
1185
+ max: (options === null || options === void 0 ? void 0 : options.max) || 200,
1186
+ ttl: (options === null || options === void 0 ? void 0 : options.ttl) || 1000 * 60 * 30, // 30分钟
1187
+ allowStale: (options === null || options === void 0 ? void 0 : options.allowStale) || false,
1188
+ updateAgeOnGet: (options === null || options === void 0 ? void 0 : options.updateAgeOnGet) || true,
1189
+ });
1190
+ }
1191
+ static getInstance(options) {
1192
+ if (!RegexCache.instance) {
1193
+ RegexCache.instance = new RegexCache(options);
1194
+ }
1195
+ return RegexCache.instance;
1196
+ }
1197
+ /**
1198
+ * 获取缓存的正则表达式
1199
+ */
1200
+ get(pattern, flags) {
1201
+ const key = flags ? `${pattern}:::${flags}` : pattern;
1202
+ let regex = this.cache.get(key);
1203
+ if (!regex) {
1204
+ try {
1205
+ regex = new RegExp(pattern, flags);
1206
+ this.cache.set(key, regex);
1207
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1208
+ }
1209
+ catch (_error) {
1210
+ // 如果正则表达式无效,抛出错误
1211
+ throw new Error(`Invalid regex pattern: ${pattern}`);
1212
+ }
1213
+ }
1214
+ return regex;
1215
+ }
1216
+ /**
1217
+ * 预编译常用正则表达式
1218
+ */
1219
+ precompile(patterns) {
1220
+ patterns.forEach(({ pattern, flags }) => {
1221
+ try {
1222
+ this.get(pattern, flags);
1223
+ }
1224
+ catch (error) {
1225
+ console.warn(`Failed to precompile regex: ${pattern}`, error);
2551
1226
  }
2552
1227
  });
2553
- };
1228
+ }
1229
+ /**
1230
+ * 获取缓存统计
1231
+ */
1232
+ getStats() {
1233
+ return {
1234
+ size: this.cache.size,
1235
+ max: this.cache.max,
1236
+ calculatedSize: this.cache.calculatedSize,
1237
+ };
1238
+ }
1239
+ /**
1240
+ * 清空缓存
1241
+ */
1242
+ clear() {
1243
+ this.cache.clear();
1244
+ }
2554
1245
  }
2555
1246
  /**
2556
- * Checks if the string is an email. If given value is not a string, then it returns false.
2557
- *
2558
- * @export
2559
- * @param {IsEmailOptions} [options]
2560
- * @param {ValidationOptions} [validationOptions]
2561
- * @returns {PropertyDecorator}
1247
+ * 性能监控
2562
1248
  */
2563
- function IsEmail(options, validationOptions) {
2564
- return function (object, propertyName) {
2565
- setExpose(object, propertyName);
2566
- registerDecorator({
2567
- name: "vIsEmail",
2568
- target: object.constructor,
2569
- propertyName,
2570
- options: validationOptions,
2571
- validator: {
2572
- validate(value, _args) {
2573
- return isEmail(value);
2574
- },
2575
- defaultMessage(_args) {
2576
- return `invalid parameter ($property).`;
2577
- }
2578
- }
2579
- });
2580
- };
1249
+ class PerformanceMonitor {
1250
+ constructor() {
1251
+ this.metrics = new Map();
1252
+ }
1253
+ static getInstance() {
1254
+ if (!PerformanceMonitor.instance) {
1255
+ PerformanceMonitor.instance = new PerformanceMonitor();
1256
+ }
1257
+ return PerformanceMonitor.instance;
1258
+ }
1259
+ /**
1260
+ * 开始计时
1261
+ */
1262
+ startTimer(name) {
1263
+ const start = performance.now();
1264
+ return () => {
1265
+ const duration = performance.now() - start;
1266
+ this.recordMetric(name, duration);
1267
+ };
1268
+ }
1269
+ /**
1270
+ * 记录性能指标
1271
+ */
1272
+ recordMetric(name, duration) {
1273
+ if (!this.metrics.has(name)) {
1274
+ this.metrics.set(name, {
1275
+ count: 0,
1276
+ totalTime: 0,
1277
+ avgTime: 0,
1278
+ maxTime: 0,
1279
+ minTime: Infinity,
1280
+ lastExecutionTime: new Date(),
1281
+ });
1282
+ }
1283
+ const metric = this.metrics.get(name);
1284
+ metric.count++;
1285
+ metric.totalTime += duration;
1286
+ metric.avgTime = metric.totalTime / metric.count;
1287
+ metric.maxTime = Math.max(metric.maxTime, duration);
1288
+ metric.minTime = Math.min(metric.minTime, duration);
1289
+ metric.lastExecutionTime = new Date();
1290
+ }
1291
+ /**
1292
+ * 获取性能报告
1293
+ */
1294
+ getReport() {
1295
+ const report = {};
1296
+ for (const [name, metric] of this.metrics) {
1297
+ report[name] = {
1298
+ ...metric,
1299
+ minTime: metric.minTime === Infinity ? 0 : metric.minTime,
1300
+ avgTimeFormatted: `${metric.avgTime.toFixed(2)}ms`,
1301
+ totalTimeFormatted: `${metric.totalTime.toFixed(2)}ms`,
1302
+ };
1303
+ }
1304
+ return report;
1305
+ }
1306
+ /**
1307
+ * 获取热点分析(执行时间最长的操作)
1308
+ */
1309
+ getHotspots(limit = 10) {
1310
+ return Array.from(this.metrics.entries())
1311
+ .map(([name, metric]) => ({
1312
+ name,
1313
+ avgTime: metric.avgTime,
1314
+ count: metric.count,
1315
+ }))
1316
+ .sort((a, b) => b.avgTime - a.avgTime)
1317
+ .slice(0, limit);
1318
+ }
1319
+ /**
1320
+ * 清空指标
1321
+ */
1322
+ clear() {
1323
+ this.metrics.clear();
1324
+ }
1325
+ /**
1326
+ * 导出性能数据为CSV格式
1327
+ */
1328
+ exportToCSV() {
1329
+ const headers = ['Name', 'Count', 'Total Time (ms)', 'Avg Time (ms)', 'Max Time (ms)', 'Min Time (ms)', 'Last Execution'];
1330
+ const rows = [headers.join(',')];
1331
+ for (const [name, metric] of this.metrics) {
1332
+ const row = [
1333
+ name,
1334
+ metric.count.toString(),
1335
+ metric.totalTime.toFixed(2),
1336
+ metric.avgTime.toFixed(2),
1337
+ metric.maxTime.toFixed(2),
1338
+ (metric.minTime === Infinity ? 0 : metric.minTime).toFixed(2),
1339
+ metric.lastExecutionTime.toISOString(),
1340
+ ];
1341
+ rows.push(row.join(','));
1342
+ }
1343
+ return rows.join('\n');
1344
+ }
2581
1345
  }
1346
+ // 导出单例实例
1347
+ const metadataCache = MetadataCache.getInstance();
1348
+ const validationCache = ValidationCache.getInstance();
1349
+ const regexCache = RegexCache.getInstance();
1350
+ const performanceMonitor = PerformanceMonitor.getInstance();
2582
1351
  /**
2583
- * Checks if the string is an IP (version 4 or 6). If given value is not a string, then it returns false.
2584
- *
2585
- * @export
2586
- * @param {number} [version]
2587
- * @param {ValidationOptions} [validationOptions]
2588
- * @returns {PropertyDecorator}
1352
+ * 缓存装饰器 - 用于缓存验证函数结果
2589
1353
  */
2590
- function IsIP(version, validationOptions) {
2591
- return function (object, propertyName) {
2592
- setExpose(object, propertyName);
2593
- registerDecorator({
2594
- name: "vIsIP",
2595
- target: object.constructor,
2596
- propertyName,
2597
- options: validationOptions,
2598
- validator: {
2599
- validate(value, _args) {
2600
- return isIP(value, version);
2601
- },
2602
- defaultMessage(_args) {
2603
- return `invalid parameter ($property).`;
1354
+ function cached(validator, ttl) {
1355
+ return function (target, propertyName, descriptor) {
1356
+ const originalMethod = descriptor.value;
1357
+ descriptor.value = function (...args) {
1358
+ const value = args[0];
1359
+ const additionalArgs = args.slice(1);
1360
+ // 尝试从缓存获取结果
1361
+ const cachedResult = validationCache.get(validator, value, ...additionalArgs);
1362
+ if (cachedResult !== undefined) {
1363
+ return cachedResult;
1364
+ }
1365
+ // 执行验证并缓存结果
1366
+ const endTimer = performanceMonitor.startTimer(validator);
1367
+ try {
1368
+ const result = originalMethod.apply(this, args);
1369
+ validationCache.set(validator, value, result, ...additionalArgs);
1370
+ // 如果指定了TTL,设置过期时间
1371
+ if (ttl && ttl > 0) {
1372
+ validationCache.setTTL(validator, value, ttl, ...additionalArgs);
2604
1373
  }
1374
+ return result;
2605
1375
  }
2606
- });
1376
+ finally {
1377
+ endTimer();
1378
+ }
1379
+ };
1380
+ return descriptor;
2607
1381
  };
2608
1382
  }
2609
1383
  /**
2610
- * Checks if the string is a valid phone number.
2611
- *
2612
- * @export
2613
- * @param {string} {string} region 2 characters uppercase country code (e.g. DE, US, CH).
2614
- * If users must enter the intl. prefix (e.g. +41), then you may pass "ZZ" or null as region.
2615
- * See [google-libphonenumber, metadata.js:countryCodeToRegionCodeMap on github]
2616
- * {@link https://github.com/ruimarinho/google-libphonenumber/blob/1e46138878cff479aafe2ce62175c6c49cb58720/src/metadata.js#L33}
2617
- * @param {ValidationOptions} [validationOptions]
2618
- * @returns {PropertyDecorator}
1384
+ * 获取所有缓存统计信息
2619
1385
  */
2620
- function IsPhoneNumber(region, validationOptions) {
2621
- return function (object, propertyName) {
2622
- setExpose(object, propertyName);
2623
- registerDecorator({
2624
- name: "vIsPhoneNumber",
2625
- target: object.constructor,
2626
- propertyName,
2627
- options: validationOptions,
2628
- validator: {
2629
- validate(value, _args) {
2630
- return isPhoneNumber(value, region);
2631
- },
2632
- defaultMessage(_args) {
2633
- return `invalid parameter ($property).`;
2634
- }
2635
- }
2636
- });
1386
+ function getAllCacheStats() {
1387
+ return {
1388
+ validation: validationCache.getStats(),
1389
+ regex: regexCache.getStats(),
1390
+ performance: performanceMonitor.getReport(),
1391
+ hotspots: performanceMonitor.getHotspots(),
2637
1392
  };
2638
1393
  }
2639
1394
  /**
2640
- * Checks if the string is an url.
2641
- *
2642
- * @export
2643
- * @param {IsURLOptions} [options]
2644
- * @param {ValidationOptions} [validationOptions]
2645
- * @returns {PropertyDecorator}
1395
+ * 预热缓存 - 预编译常用正则表达式
2646
1396
  */
2647
- function IsUrl(options, validationOptions) {
2648
- return function (object, propertyName) {
2649
- setExpose(object, propertyName);
2650
- registerDecorator({
2651
- name: "vIsUrl",
2652
- target: object.constructor,
2653
- propertyName,
2654
- options: validationOptions,
2655
- validator: {
2656
- validate(value, _args) {
2657
- return isURL(value, options);
2658
- },
2659
- defaultMessage(_args) {
2660
- return `invalid parameter ($property).`;
2661
- }
2662
- }
2663
- });
2664
- };
1397
+ function warmupCaches() {
1398
+ // 预编译中文验证相关的正则表达式
1399
+ const commonPatterns = [
1400
+ { pattern: '^[\u4e00-\u9fa5]{2,8}$' }, // 中文姓名
1401
+ { pattern: '^1[3-9]\\d{9}$' }, // 手机号
1402
+ { pattern: '^\\d{6}$' }, // 邮政编码
1403
+ { pattern: '^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼]' }, // 车牌号开头
1404
+ ];
1405
+ regexCache.precompile(commonPatterns);
2665
1406
  }
2666
1407
  /**
2667
- * check if the string is a hash of type algorithm. Algorithm is one of ['md4', 'md5', 'sha1', 'sha256',
2668
- * 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', 'tiger160', 'tiger192', 'crc32', 'crc32b']
2669
- *
2670
- * @export
2671
- * @param {HashAlgorithm} algorithm
2672
- * @param {ValidationOptions} [validationOptions]
2673
- * @returns {PropertyDecorator}
1408
+ * 清空所有缓存
2674
1409
  */
2675
- function IsHash(algorithm, validationOptions) {
2676
- return function (object, propertyName) {
2677
- setExpose(object, propertyName);
2678
- registerDecorator({
2679
- name: "vIsHash",
2680
- target: object.constructor,
2681
- propertyName,
2682
- options: validationOptions,
2683
- validator: {
2684
- validate(value, _args) {
2685
- return isHash(value, algorithm);
2686
- },
2687
- defaultMessage(_args) {
2688
- return `invalid parameter, ($property) must be is an ${algorithm} Hash string.`;
2689
- }
2690
- }
2691
- });
2692
- };
1410
+ function clearAllCaches() {
1411
+ validationCache.clear();
1412
+ regexCache.clear();
1413
+ performanceMonitor.clear();
2693
1414
  }
2694
1415
  /**
2695
- * Use a custom function for validation
2696
- * @param func
2697
- * @param validationOptions
2698
- * @returns
1416
+ * 配置缓存设置
2699
1417
  */
2700
- function CheckFunc(func, validationOptions) {
2701
- return function (object, propertyName) {
2702
- setExpose(object, propertyName);
2703
- registerDecorator({
2704
- name: "vCheckFunc",
2705
- target: object.constructor,
2706
- propertyName,
2707
- options: validationOptions,
2708
- validator: {
2709
- validate(value, _args) {
2710
- return func(value);
2711
- },
2712
- defaultMessage(_args) {
2713
- return `invalid parameter ($property).`;
2714
- }
2715
- }
2716
- });
2717
- };
1418
+ function configureCaches(options) {
1419
+ if (options.validation) {
1420
+ // 重新创建验证缓存实例
1421
+ ValidationCache.instance = new ValidationCache(options.validation);
1422
+ }
1423
+ if (options.regex) {
1424
+ // 重新创建正则缓存实例
1425
+ RegexCache.instance = new RegexCache(options.regex);
1426
+ }
2718
1427
  }
2719
1428
 
2720
- export { CheckFunc, 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, ValidFuncs, Validated, checkParamsType, convertDtoParamsType, convertParamsType, paramterTypes, plainToClass };
1429
+ export { ClassValidator, Contains, ENABLE_VALIDATED, ERROR_MESSAGES, Equals, ErrorMessageFormatter, Expose, FunctionValidator, Gt, Gte, IsCnName, IsDate, IsDefined, IsEmail, IsHash, IsIP, IsIdNumber, IsIn, IsMobile, IsNotEmpty, IsNotIn, IsPhoneNumber, IsPlateNumber, IsUrl, IsZipCode, KoattyValidationError, Lt, Lte, NotEquals, PARAM_CHECK_KEY, PARAM_RULE_KEY, Valid, ValidFuncs, Validated, cached, checkParamsType, clearAllCaches, configureCaches, convertDtoParamsType, convertParamsType, createParameterizedDecorator, createSimpleDecorator, createValidationDecorator, createValidationError, createValidationErrors, errorFormatter, getAllCacheStats, metadataCache, paramterTypes, performanceMonitor, plainToClass, regexCache, setValidationLanguage, validationCache, warmupCaches };