knight-validation 4.0.0 → 4.0.2
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/lib/lib/Validator.d.ts +12 -5
- package/lib/lib/Validator.js +73 -12
- package/package.json +1 -1
package/lib/lib/Validator.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { Misfit } from 'knight-misfit';
|
|
2
2
|
import { Constraint } from './Constraint';
|
|
3
|
+
export interface ValidatorMap {
|
|
4
|
+
[validatorId: string]: Validator;
|
|
5
|
+
}
|
|
3
6
|
export interface ValidatorOptions {
|
|
4
7
|
checkOnlyWhatIsThere?: boolean;
|
|
5
8
|
exclude?: string[];
|
|
@@ -10,13 +13,18 @@ export interface ValidatorEntry<T = any> {
|
|
|
10
13
|
validator?: Validator;
|
|
11
14
|
condition?: (object: T) => Promise<boolean>;
|
|
12
15
|
}
|
|
13
|
-
declare
|
|
14
|
-
|
|
16
|
+
export declare class ValidatorFactory<T = any> {
|
|
17
|
+
validatorId: string;
|
|
18
|
+
createFn: (validators: ValidatorMap) => Validator<T>;
|
|
19
|
+
constructor(validatorId: string | (new (...args: any[]) => any), createFn: (validators: ValidatorMap) => Validator<T>);
|
|
20
|
+
createOrGetExisting(validators: ValidatorMap): Validator<T>;
|
|
15
21
|
}
|
|
16
22
|
export declare class Validator<T = any> {
|
|
23
|
+
validatorId: string;
|
|
17
24
|
options?: ValidatorOptions;
|
|
25
|
+
validators: ValidatorMap;
|
|
18
26
|
entries: ValidatorEntry<T>[];
|
|
19
|
-
constructor(options?: ValidatorOptions);
|
|
27
|
+
constructor(validators?: ValidatorMap, options?: ValidatorOptions, validatorId?: string | (new (...args: any[]) => any));
|
|
20
28
|
add(constraint: Constraint, condition?: (object: T) => Promise<boolean>): void;
|
|
21
29
|
add(constraintName: string, validate: (value: any) => Promise<Misfit | null>, condition?: (object: T) => Promise<boolean>): void;
|
|
22
30
|
add(validatorFactory: ValidatorFactory): void;
|
|
@@ -26,6 +34,5 @@ export declare class Validator<T = any> {
|
|
|
26
34
|
add(properties: string[], constraint: Constraint, condition?: (object: T) => Promise<boolean>): void;
|
|
27
35
|
add(properties: string[], constraintName: string, validate: (object: T, properties: string[]) => Promise<Misfit | null>, condition?: (object: T) => Promise<boolean>): void;
|
|
28
36
|
add(validatorEntry: ValidatorEntry): void;
|
|
29
|
-
validate(object: T, options?: ValidatorOptions): Promise<Misfit[]>;
|
|
37
|
+
validate(object: T, options?: ValidatorOptions, validated?: WeakSet<any>): Promise<Misfit[]>;
|
|
30
38
|
}
|
|
31
|
-
export {};
|
package/lib/lib/Validator.js
CHANGED
|
@@ -9,18 +9,45 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.Validator = void 0;
|
|
12
|
+
exports.Validator = exports.ValidatorFactory = void 0;
|
|
13
13
|
const knight_log_1 = require("knight-log");
|
|
14
14
|
const Constraint_1 = require("./Constraint");
|
|
15
15
|
const DotNotation_1 = require("./DotNotation");
|
|
16
16
|
const QuickConstraint_1 = require("./constraints/QuickConstraint");
|
|
17
17
|
let log = new knight_log_1.Log('knight-validation/Validator.ts');
|
|
18
18
|
class ValidatorFactory {
|
|
19
|
+
constructor(validatorId, createFn) {
|
|
20
|
+
this.validatorId = typeof validatorId == 'string' ? validatorId : validatorId.name;
|
|
21
|
+
this.createFn = createFn;
|
|
22
|
+
}
|
|
23
|
+
createOrGetExisting(validators) {
|
|
24
|
+
let l = log.cls('ValidatorFactory', 'createOrGetExisting');
|
|
25
|
+
l.param('validators', validators);
|
|
26
|
+
l.creator('this.validatorId', this.validatorId);
|
|
27
|
+
if (this.validatorId in validators) {
|
|
28
|
+
l.returning('existing validator', validators[this.validatorId]);
|
|
29
|
+
return validators[this.validatorId];
|
|
30
|
+
}
|
|
31
|
+
l.returning('created validator');
|
|
32
|
+
return this.createFn(validators);
|
|
33
|
+
}
|
|
19
34
|
}
|
|
35
|
+
exports.ValidatorFactory = ValidatorFactory;
|
|
20
36
|
class Validator {
|
|
21
|
-
constructor(options) {
|
|
37
|
+
constructor(validators, options, validatorId) {
|
|
22
38
|
this.entries = [];
|
|
23
39
|
this.options = options;
|
|
40
|
+
this.validators = validators || {};
|
|
41
|
+
if (typeof validatorId == 'string') {
|
|
42
|
+
this.validatorId = validatorId;
|
|
43
|
+
}
|
|
44
|
+
else if (typeof validatorId == 'function') {
|
|
45
|
+
this.validatorId = validatorId.name;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
this.validatorId = this.constructor.name;
|
|
49
|
+
}
|
|
50
|
+
this.validators[this.validatorId] = this;
|
|
24
51
|
}
|
|
25
52
|
add(...args) {
|
|
26
53
|
var _a, _b, _c;
|
|
@@ -30,20 +57,35 @@ class Validator {
|
|
|
30
57
|
let constraint;
|
|
31
58
|
let validatorFactory;
|
|
32
59
|
let condition;
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
60
|
+
if (args[0] instanceof ValidatorFactory) {
|
|
61
|
+
if (this.options == undefined) {
|
|
62
|
+
this.options = {};
|
|
63
|
+
}
|
|
64
|
+
let validator = args[0].createOrGetExisting(this.validators);
|
|
65
|
+
if (validator == this) {
|
|
66
|
+
throw new Error('Cannot add add another validator that is itself which would result in an endless loop of adding itself!');
|
|
67
|
+
}
|
|
68
|
+
if (typeof validator == 'object' &&
|
|
69
|
+
validator !== null &&
|
|
70
|
+
'entries' in validator &&
|
|
71
|
+
Array.isArray(validator.entries) &&
|
|
72
|
+
validator.entries.length > 0) {
|
|
73
|
+
l.dev('Adding entries from validator', validator);
|
|
36
74
|
for (let entry of validator.entries) {
|
|
37
75
|
this.add(entry);
|
|
38
76
|
}
|
|
39
77
|
}
|
|
78
|
+
else {
|
|
79
|
+
l.warn('Given validator to add does not have any entries!', validator);
|
|
80
|
+
}
|
|
40
81
|
}
|
|
41
82
|
else if (typeof args[0] == 'object' && args[0] !== null && 'properties' in args[0] && Array.isArray(args[0].properties)) {
|
|
42
83
|
properties = args[0].properties;
|
|
43
84
|
constraint = args[0].constraint;
|
|
44
|
-
validatorFactory = args[0].validator ?
|
|
45
|
-
{ create: () => args[0].validator } : undefined;
|
|
46
85
|
condition = args[0].condition;
|
|
86
|
+
if (args[0].validator) {
|
|
87
|
+
validatorFactory = new ValidatorFactory(args[0].validator.constructor.name, () => args[0].validator);
|
|
88
|
+
}
|
|
47
89
|
if (constraint != undefined && validatorFactory != undefined) {
|
|
48
90
|
throw new Error('The provided parameter is a ValidatorEntry with both a constraint and a validator defined. This is invalid! Only one may be specified at a time!');
|
|
49
91
|
}
|
|
@@ -73,7 +115,7 @@ class Validator {
|
|
|
73
115
|
constraint = args[1];
|
|
74
116
|
condition = args.length > 2 ? args[2] : undefined;
|
|
75
117
|
}
|
|
76
|
-
else if (
|
|
118
|
+
else if (args[1] instanceof ValidatorFactory) {
|
|
77
119
|
validatorFactory = args[1];
|
|
78
120
|
condition = args.length > 2 ? args[2] : undefined;
|
|
79
121
|
}
|
|
@@ -98,10 +140,20 @@ class Validator {
|
|
|
98
140
|
}
|
|
99
141
|
}
|
|
100
142
|
if (!propertyExcluded) {
|
|
143
|
+
let validator;
|
|
144
|
+
if (validatorFactory) {
|
|
145
|
+
if (this.options == undefined) {
|
|
146
|
+
this.options = {};
|
|
147
|
+
}
|
|
148
|
+
validator = validatorFactory.createOrGetExisting(this.validators);
|
|
149
|
+
if (validator == undefined) {
|
|
150
|
+
throw new Error('Validator factory did not create a validator!');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
101
153
|
let entry = {
|
|
102
154
|
properties: properties,
|
|
103
155
|
constraint: constraint,
|
|
104
|
-
validator:
|
|
156
|
+
validator: validator,
|
|
105
157
|
condition: condition
|
|
106
158
|
};
|
|
107
159
|
this.entries.push(entry);
|
|
@@ -109,17 +161,22 @@ class Validator {
|
|
|
109
161
|
}
|
|
110
162
|
l.returning();
|
|
111
163
|
}
|
|
112
|
-
validate(object, options) {
|
|
164
|
+
validate(object, options, validated) {
|
|
113
165
|
return __awaiter(this, void 0, void 0, function* () {
|
|
114
166
|
var _a;
|
|
115
167
|
let l = log.mt('validate');
|
|
116
168
|
l.param('object', object);
|
|
117
169
|
l.param('options', options);
|
|
170
|
+
if (validated == undefined) {
|
|
171
|
+
validated = new WeakSet;
|
|
172
|
+
}
|
|
173
|
+
validated.add(object);
|
|
118
174
|
options = options || this.options;
|
|
119
175
|
let misfits = [];
|
|
120
176
|
let misfittingProperties = [];
|
|
121
177
|
for (let entry of this.entries) {
|
|
122
178
|
let constraintOrValidatorName = entry.constraint ? (_a = entry.constraint) === null || _a === void 0 ? void 0 : _a.name : entry.validator ? entry.validator.constructor.name : '';
|
|
179
|
+
l.dev('Checking constraint', JSON.stringify(entry.properties), constraintOrValidatorName);
|
|
123
180
|
l.location = ['' + JSON.stringify(entry.properties) + ' > ' + constraintOrValidatorName];
|
|
124
181
|
let propertyAlreadyHasAMisfit = false;
|
|
125
182
|
for (let property of entry.properties) {
|
|
@@ -205,6 +262,10 @@ class Validator {
|
|
|
205
262
|
l.dev('Value of the property is not of type object or null. Skipping...', value);
|
|
206
263
|
continue;
|
|
207
264
|
}
|
|
265
|
+
if (validated.has(value)) {
|
|
266
|
+
l.dev('Object is or was already being validated. Skipping...', value);
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
208
269
|
if (value instanceof Array) {
|
|
209
270
|
l.dev('Value of the property is an array. Iterating its elements...');
|
|
210
271
|
for (let i = 0; i < value.length; i++) {
|
|
@@ -213,7 +274,7 @@ class Validator {
|
|
|
213
274
|
continue;
|
|
214
275
|
}
|
|
215
276
|
l.calling('entry.validator.validate', value[i], options);
|
|
216
|
-
let subMisfits = yield entry.validator.validate(value[i], options);
|
|
277
|
+
let subMisfits = yield entry.validator.validate(value[i], options, validated);
|
|
217
278
|
l.called('entry.validator.validate');
|
|
218
279
|
if (subMisfits.length > 0) {
|
|
219
280
|
l.dev('Validator returned misfits', subMisfits);
|
|
@@ -234,7 +295,7 @@ class Validator {
|
|
|
234
295
|
else {
|
|
235
296
|
l.dev('Value of the property is not an array');
|
|
236
297
|
l.calling('entry.validator.validate', value, options);
|
|
237
|
-
let subMisfits = yield entry.validator.validate(value, options);
|
|
298
|
+
let subMisfits = yield entry.validator.validate(value, options, validated);
|
|
238
299
|
l.called('entry.validator.validate');
|
|
239
300
|
if (subMisfits.length > 0) {
|
|
240
301
|
l.dev('Validator returned misfits', subMisfits);
|