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/.rollup.config.js +62 -59
- package/.vscode/launch.json +81 -0
- package/CHANGELOG.md +83 -75
- package/LICENSE +29 -29
- package/README.md +363 -116
- package/coverage.lcov +1607 -0
- package/dist/LICENSE +29 -29
- package/dist/README.md +363 -116
- package/dist/index.d.ts +421 -219
- package/dist/index.js +799 -2074
- package/dist/index.mjs +768 -2059
- package/dist/package.json +91 -94
- package/examples/README.md +90 -0
- package/examples/basic-usage.ts +239 -0
- package/examples/custom-decorators-example.ts +230 -0
- package/examples/usage-example.ts +284 -0
- package/package.json +91 -94
package/dist/index.mjs
CHANGED
|
@@ -1,1423 +1,15 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @Author: richen
|
|
3
|
-
* @Date:
|
|
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
|
|
11
|
-
|
|
12
|
-
|
|
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 (
|
|
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-
|
|
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
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1985
|
-
|
|
652
|
+
let validOptions;
|
|
653
|
+
if (typeof options === 'string') {
|
|
654
|
+
validOptions = { message: options, value: null };
|
|
1986
655
|
}
|
|
1987
|
-
|
|
1988
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
2035
|
-
*
|
|
2036
|
-
* @
|
|
2037
|
-
* @returns {MethodDecorator}
|
|
670
|
+
* 创建验证装饰器的工厂函数
|
|
671
|
+
* @param options 装饰器配置选项
|
|
672
|
+
* @returns 装饰器工厂函数
|
|
2038
673
|
*/
|
|
2039
|
-
function
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
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
|
-
*
|
|
2075
|
-
*
|
|
2076
|
-
* @
|
|
2077
|
-
* @
|
|
711
|
+
* 创建简单验证装饰器(不需要额外参数)
|
|
712
|
+
* @param name 装饰器名称
|
|
713
|
+
* @param validator 验证函数
|
|
714
|
+
* @param defaultMessage 默认错误信息
|
|
715
|
+
* @returns 装饰器函数
|
|
2078
716
|
*/
|
|
2079
|
-
function
|
|
2080
|
-
return
|
|
2081
|
-
|
|
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
|
-
*
|
|
2086
|
-
*
|
|
2087
|
-
* @
|
|
2088
|
-
* @
|
|
726
|
+
* 创建带参数的验证装饰器
|
|
727
|
+
* @param name 装饰器名称
|
|
728
|
+
* @param validator 验证函数
|
|
729
|
+
* @param defaultMessage 默认错误信息
|
|
730
|
+
* @returns 装饰器工厂函数
|
|
2089
731
|
*/
|
|
2090
|
-
function
|
|
2091
|
-
return
|
|
2092
|
-
|
|
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
|
-
*
|
|
2097
|
-
*
|
|
2098
|
-
* @export
|
|
2099
|
-
* @param {string} property
|
|
2100
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2101
|
-
* @returns {PropertyDecorator}
|
|
742
|
+
* 重构后的装饰器定义 - 使用工厂函数消除重复
|
|
743
|
+
* @author richen
|
|
2102
744
|
*/
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
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
|
-
*
|
|
2124
|
-
*
|
|
2125
|
-
* @export
|
|
2126
|
-
* @param {string} property
|
|
2127
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2128
|
-
* @returns {PropertyDecorator}
|
|
783
|
+
* 标记属性为可导出
|
|
2129
784
|
*/
|
|
2130
|
-
function
|
|
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
|
-
*
|
|
2151
|
-
*
|
|
2152
|
-
* @export
|
|
2153
|
-
* @param {string} property
|
|
2154
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2155
|
-
* @returns {PropertyDecorator}
|
|
791
|
+
* Expose的别名
|
|
2156
792
|
*/
|
|
2157
|
-
function
|
|
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
|
-
*
|
|
2178
|
-
*
|
|
2179
|
-
* @export
|
|
2180
|
-
* @param {string} property
|
|
2181
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2182
|
-
* @returns {PropertyDecorator}
|
|
799
|
+
* 参数验证装饰器
|
|
2183
800
|
*/
|
|
2184
|
-
function
|
|
2185
|
-
return function (object, propertyName) {
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
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
|
-
*
|
|
2205
|
-
*
|
|
2206
|
-
* @export
|
|
2207
|
-
* @param {string} property
|
|
2208
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2209
|
-
* @returns {PropertyDecorator}
|
|
810
|
+
* 方法验证装饰器
|
|
2210
811
|
*/
|
|
2211
|
-
function
|
|
2212
|
-
return function (object, propertyName) {
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
2258
|
-
*
|
|
2259
|
-
* @export
|
|
2260
|
-
* @param {*} comparison
|
|
2261
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2262
|
-
* @returns {PropertyDecorator}
|
|
828
|
+
* 错误信息国际化
|
|
2263
829
|
*/
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
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
|
-
*
|
|
2285
|
-
*
|
|
2286
|
-
* @export
|
|
2287
|
-
* @param {*} comparison
|
|
2288
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2289
|
-
* @returns {PropertyDecorator}
|
|
891
|
+
* 增强的验证错误类
|
|
2290
892
|
*/
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
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
|
-
*
|
|
2312
|
-
*
|
|
2313
|
-
* @export
|
|
2314
|
-
* @param {string} seed
|
|
2315
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2316
|
-
* @returns {PropertyDecorator}
|
|
930
|
+
* 错误信息格式化器
|
|
2317
931
|
*/
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
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
|
-
*
|
|
2340
|
-
*
|
|
2341
|
-
* @export
|
|
2342
|
-
* @param {any[]} possibleValues
|
|
2343
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2344
|
-
* @returns {PropertyDecorator}
|
|
991
|
+
* 全局错误信息格式化器实例
|
|
2345
992
|
*/
|
|
2346
|
-
|
|
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
|
-
*
|
|
2367
|
-
*
|
|
2368
|
-
* @export
|
|
2369
|
-
* @param {any[]} possibleValues
|
|
2370
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2371
|
-
* @returns {PropertyDecorator}
|
|
995
|
+
* 设置全局语言
|
|
2372
996
|
*/
|
|
2373
|
-
function
|
|
2374
|
-
|
|
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
|
-
*
|
|
2394
|
-
*
|
|
2395
|
-
* @export
|
|
2396
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2397
|
-
* @returns {PropertyDecorator}
|
|
1001
|
+
* 创建验证错误
|
|
2398
1002
|
*/
|
|
2399
|
-
function
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
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
|
-
*
|
|
2420
|
-
*
|
|
2421
|
-
* @export
|
|
2422
|
-
* @param {number} min
|
|
2423
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2424
|
-
* @returns {PropertyDecorator}
|
|
1014
|
+
* 批量创建验证错误
|
|
2425
1015
|
*/
|
|
2426
|
-
function
|
|
2427
|
-
|
|
2428
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
2474
|
-
*
|
|
2475
|
-
* @export
|
|
2476
|
-
* @param {number} min
|
|
2477
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2478
|
-
* @returns {PropertyDecorator}
|
|
1026
|
+
* 元数据缓存
|
|
2479
1027
|
*/
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
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
|
-
*
|
|
2501
|
-
*
|
|
2502
|
-
* @export
|
|
2503
|
-
* @param {number} max
|
|
2504
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2505
|
-
* @returns {PropertyDecorator}
|
|
1078
|
+
* 验证结果缓存
|
|
2506
1079
|
*/
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
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
|
-
*
|
|
2557
|
-
*
|
|
2558
|
-
* @export
|
|
2559
|
-
* @param {IsEmailOptions} [options]
|
|
2560
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2561
|
-
* @returns {PropertyDecorator}
|
|
1247
|
+
* 性能监控
|
|
2562
1248
|
*/
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
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
|
-
*
|
|
2584
|
-
*
|
|
2585
|
-
* @export
|
|
2586
|
-
* @param {number} [version]
|
|
2587
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2588
|
-
* @returns {PropertyDecorator}
|
|
1352
|
+
* 缓存装饰器 - 用于缓存验证函数结果
|
|
2589
1353
|
*/
|
|
2590
|
-
function
|
|
2591
|
-
return function (
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
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
|
-
*
|
|
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
|
|
2621
|
-
return
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
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
|
-
*
|
|
2641
|
-
*
|
|
2642
|
-
* @export
|
|
2643
|
-
* @param {IsURLOptions} [options]
|
|
2644
|
-
* @param {ValidationOptions} [validationOptions]
|
|
2645
|
-
* @returns {PropertyDecorator}
|
|
1395
|
+
* 预热缓存 - 预编译常用正则表达式
|
|
2646
1396
|
*/
|
|
2647
|
-
function
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
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
|
-
*
|
|
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
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
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
|
-
*
|
|
2696
|
-
* @param func
|
|
2697
|
-
* @param validationOptions
|
|
2698
|
-
* @returns
|
|
1416
|
+
* 配置缓存设置
|
|
2699
1417
|
*/
|
|
2700
|
-
function
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
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 {
|
|
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 };
|