knight-validation 4.0.1 → 4.0.3
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 -9
- package/lib/lib/Validator.js +71 -17
- 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,18 +13,18 @@ export interface ValidatorEntry<T = any> {
|
|
|
10
13
|
validator?: Validator;
|
|
11
14
|
condition?: (object: T) => Promise<boolean>;
|
|
12
15
|
}
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
constructor(createFn: () => Validator<T>);
|
|
19
|
-
create(): Validator<T>;
|
|
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>;
|
|
20
21
|
}
|
|
21
22
|
export declare class Validator<T = any> {
|
|
23
|
+
validatorId: string;
|
|
22
24
|
options?: ValidatorOptions;
|
|
25
|
+
validators: ValidatorMap;
|
|
23
26
|
entries: ValidatorEntry<T>[];
|
|
24
|
-
constructor(options?: ValidatorOptions);
|
|
27
|
+
constructor(options?: ValidatorOptions, validators?: ValidatorMap, validatorId?: string | (new (...args: any[]) => any));
|
|
25
28
|
add(constraint: Constraint, condition?: (object: T) => Promise<boolean>): void;
|
|
26
29
|
add(constraintName: string, validate: (value: any) => Promise<Misfit | null>, condition?: (object: T) => Promise<boolean>): void;
|
|
27
30
|
add(validatorFactory: ValidatorFactory): void;
|
|
@@ -31,5 +34,5 @@ export declare class Validator<T = any> {
|
|
|
31
34
|
add(properties: string[], constraint: Constraint, condition?: (object: T) => Promise<boolean>): void;
|
|
32
35
|
add(properties: string[], constraintName: string, validate: (object: T, properties: string[]) => Promise<Misfit | null>, condition?: (object: T) => Promise<boolean>): void;
|
|
33
36
|
add(validatorEntry: ValidatorEntry): void;
|
|
34
|
-
validate(object: T, options?: ValidatorOptions): Promise<Misfit[]>;
|
|
37
|
+
validate(object: T, options?: ValidatorOptions, validated?: WeakSet<any>): Promise<Misfit[]>;
|
|
35
38
|
}
|
package/lib/lib/Validator.js
CHANGED
|
@@ -9,25 +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 = exports.
|
|
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
|
-
class
|
|
19
|
-
constructor(createFn) {
|
|
18
|
+
class ValidatorFactory {
|
|
19
|
+
constructor(validatorId, createFn) {
|
|
20
|
+
this.validatorId = typeof validatorId == 'string' ? validatorId : validatorId.name;
|
|
20
21
|
this.createFn = createFn;
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
|
|
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);
|
|
24
33
|
}
|
|
25
34
|
}
|
|
26
|
-
exports.
|
|
35
|
+
exports.ValidatorFactory = ValidatorFactory;
|
|
27
36
|
class Validator {
|
|
28
|
-
constructor(options) {
|
|
37
|
+
constructor(options, validators, validatorId) {
|
|
29
38
|
this.entries = [];
|
|
30
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;
|
|
31
51
|
}
|
|
32
52
|
add(...args) {
|
|
33
53
|
var _a, _b, _c;
|
|
@@ -37,20 +57,35 @@ class Validator {
|
|
|
37
57
|
let constraint;
|
|
38
58
|
let validatorFactory;
|
|
39
59
|
let condition;
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
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);
|
|
43
74
|
for (let entry of validator.entries) {
|
|
44
75
|
this.add(entry);
|
|
45
76
|
}
|
|
46
77
|
}
|
|
78
|
+
else {
|
|
79
|
+
l.warn('Given validator to add does not have any entries!', validator);
|
|
80
|
+
}
|
|
47
81
|
}
|
|
48
82
|
else if (typeof args[0] == 'object' && args[0] !== null && 'properties' in args[0] && Array.isArray(args[0].properties)) {
|
|
49
83
|
properties = args[0].properties;
|
|
50
84
|
constraint = args[0].constraint;
|
|
51
|
-
validatorFactory = args[0].validator ?
|
|
52
|
-
{ create: () => args[0].validator } : undefined;
|
|
53
85
|
condition = args[0].condition;
|
|
86
|
+
if (args[0].validator) {
|
|
87
|
+
validatorFactory = new ValidatorFactory(args[0].validator.constructor.name, () => args[0].validator);
|
|
88
|
+
}
|
|
54
89
|
if (constraint != undefined && validatorFactory != undefined) {
|
|
55
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!');
|
|
56
91
|
}
|
|
@@ -80,7 +115,7 @@ class Validator {
|
|
|
80
115
|
constraint = args[1];
|
|
81
116
|
condition = args.length > 2 ? args[2] : undefined;
|
|
82
117
|
}
|
|
83
|
-
else if (
|
|
118
|
+
else if (args[1] instanceof ValidatorFactory) {
|
|
84
119
|
validatorFactory = args[1];
|
|
85
120
|
condition = args.length > 2 ? args[2] : undefined;
|
|
86
121
|
}
|
|
@@ -105,10 +140,20 @@ class Validator {
|
|
|
105
140
|
}
|
|
106
141
|
}
|
|
107
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
|
+
}
|
|
108
153
|
let entry = {
|
|
109
154
|
properties: properties,
|
|
110
155
|
constraint: constraint,
|
|
111
|
-
validator:
|
|
156
|
+
validator: validator,
|
|
112
157
|
condition: condition
|
|
113
158
|
};
|
|
114
159
|
this.entries.push(entry);
|
|
@@ -116,17 +161,22 @@ class Validator {
|
|
|
116
161
|
}
|
|
117
162
|
l.returning();
|
|
118
163
|
}
|
|
119
|
-
validate(object, options) {
|
|
164
|
+
validate(object, options, validated) {
|
|
120
165
|
return __awaiter(this, void 0, void 0, function* () {
|
|
121
166
|
var _a;
|
|
122
167
|
let l = log.mt('validate');
|
|
123
168
|
l.param('object', object);
|
|
124
169
|
l.param('options', options);
|
|
170
|
+
if (validated == undefined) {
|
|
171
|
+
validated = new WeakSet;
|
|
172
|
+
}
|
|
173
|
+
validated.add(object);
|
|
125
174
|
options = options || this.options;
|
|
126
175
|
let misfits = [];
|
|
127
176
|
let misfittingProperties = [];
|
|
128
177
|
for (let entry of this.entries) {
|
|
129
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);
|
|
130
180
|
l.location = ['' + JSON.stringify(entry.properties) + ' > ' + constraintOrValidatorName];
|
|
131
181
|
let propertyAlreadyHasAMisfit = false;
|
|
132
182
|
for (let property of entry.properties) {
|
|
@@ -212,6 +262,10 @@ class Validator {
|
|
|
212
262
|
l.dev('Value of the property is not of type object or null. Skipping...', value);
|
|
213
263
|
continue;
|
|
214
264
|
}
|
|
265
|
+
if (validated.has(value)) {
|
|
266
|
+
l.dev('Object is or was already being validated. Skipping...', value);
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
215
269
|
if (value instanceof Array) {
|
|
216
270
|
l.dev('Value of the property is an array. Iterating its elements...');
|
|
217
271
|
for (let i = 0; i < value.length; i++) {
|
|
@@ -220,7 +274,7 @@ class Validator {
|
|
|
220
274
|
continue;
|
|
221
275
|
}
|
|
222
276
|
l.calling('entry.validator.validate', value[i], options);
|
|
223
|
-
let subMisfits = yield entry.validator.validate(value[i], options);
|
|
277
|
+
let subMisfits = yield entry.validator.validate(value[i], options, validated);
|
|
224
278
|
l.called('entry.validator.validate');
|
|
225
279
|
if (subMisfits.length > 0) {
|
|
226
280
|
l.dev('Validator returned misfits', subMisfits);
|
|
@@ -241,7 +295,7 @@ class Validator {
|
|
|
241
295
|
else {
|
|
242
296
|
l.dev('Value of the property is not an array');
|
|
243
297
|
l.calling('entry.validator.validate', value, options);
|
|
244
|
-
let subMisfits = yield entry.validator.validate(value, options);
|
|
298
|
+
let subMisfits = yield entry.validator.validate(value, options, validated);
|
|
245
299
|
l.called('entry.validator.validate');
|
|
246
300
|
if (subMisfits.length > 0) {
|
|
247
301
|
l.dev('Validator returned misfits', subMisfits);
|