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.
@@ -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 interface ValidatorFactory<T = any> {
14
- create(): Validator<T>;
15
- }
16
- export declare class SimpleValidatorFactory<T = any> implements ValidatorFactory<T> {
17
- createFn: () => Validator<T>;
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
  }
@@ -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.SimpleValidatorFactory = 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
- class SimpleValidatorFactory {
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
- create() {
23
- return this.createFn();
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.SimpleValidatorFactory = SimpleValidatorFactory;
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 (typeof args[0] == 'object' && args[0] !== null && 'create' in args[0] && typeof args[0].create == 'function') {
41
- let validator = args[0].create();
42
- if (typeof validator == 'object' && validator !== null && 'entries' in validator && Array.isArray(validator.entries)) {
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 (typeof args[1] == 'object' && args[1] !== null && 'create' in args[1] && typeof args[1].create == 'function') {
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: validatorFactory ? validatorFactory.create() : undefined,
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knight-validation",
3
- "version": "4.0.1",
3
+ "version": "4.0.3",
4
4
  "description": "A validation lib",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",