knight-validation 2.0.3 → 2.0.5

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/README.md CHANGED
@@ -33,7 +33,14 @@ import { Validator } from 'knight-validation'
33
33
  class UserValidator extends Validator {
34
34
  constructor(userDb: UserDb) {
35
35
  super()
36
- this.add(['firstName', 'lastName'], ...)
36
+
37
+ this.add(['firstName', 'lastName'], 'Different', async (user: User) => {
38
+ if (user.firstName == user.lastName) {
39
+ // You do not need to set the constraint name nor the properties on the misfit.
40
+ // Those will be set automatically.
41
+ return new Misfit
42
+ }
43
+ })
37
44
  }
38
45
  }
39
46
  ```
@@ -44,6 +51,11 @@ class UserValidator extends Validator {
44
51
  // Check if a property is absent
45
52
  new Absent
46
53
 
54
+ // Check if a number is greater and/or lesser than a given number
55
+ new Bounds({ greaterThan: 0, lesserThan: 10 })
56
+ // Check if a number is greater and/or lesser than or equal a given number
57
+ new Bounds({ greaterThanEqual: 0, lesserThanqEqual: 10 })
58
+
47
59
  // Check a property's value equals one of the three given strings
48
60
  new Enum('Moni', 'Lisa', 'Anna')
49
61
  // Check if a property's value equals one of the three given numbers
@@ -54,6 +66,11 @@ new Exists(async (user: User) => {
54
66
  // Return true if your exists condition is met
55
67
  })
56
68
 
69
+ // Check if the length of a string has a minmum and/or maximum length
70
+ new Length({ min: 5, max: 10})
71
+ // Check if the length of a string has exactly a specific length
72
+ new Length({ exact: 5 })
73
+
57
74
  // Check if a property is there
58
75
  new Required
59
76
 
@@ -85,19 +102,16 @@ misfits.length == 1
85
102
  A misfit contains the following informations by default.
86
103
 
87
104
  ```typescript
88
- // The name of the misfit which defaults to the name of the constraint which was not met
105
+ // The name of the constraint that resulted in the misfit
89
106
  misfit.constraint == 'Required'
90
107
 
91
- // The property where the misfit occured
92
- misfit.property == 'email'
93
-
94
- // The properties where the misfit occured
95
- misfit.properties == ['firstName', 'lastName']
108
+ // The involved properties
109
+ misfit.property == [ 'email' ]
96
110
 
97
- // It contains any information that is useful about why checking the constraint resulted in a misfit (Optional)
98
- misfit.value
111
+ // Contextual values specific to the misfit at hand (Optional)
112
+ misfit.values
99
113
 
100
- // A message (Optional)
114
+ // A misfit message (Optional)
101
115
  misift.message == 'The property email is required.'
102
116
  ```
103
117
 
@@ -129,40 +143,46 @@ class UserValidator extends Validator {
129
143
  }
130
144
  ```
131
145
 
132
- #### Exclude rules
133
-
134
- ```typescript
135
- // Exclude all constraints regarding the email property
136
- let misfits = validator.validate(user, { exclude: ['email'] })
137
-
138
- // Exclude only the required constraint of the email property
139
- let misfits = validator.validate(user, { exclude: [{ properties: 'email', constraint: 'Required' }] })
140
- ```
141
-
142
146
  ### Anonymous custom constraints
143
147
 
144
- You can add constraints on the fly without creating a class.
148
+ You can create custom constraints on the fly without having to create a dedicated constraint class.
145
149
 
146
150
  ```typescript
147
151
  let validator = new Validator
148
152
 
153
+ // Second parameter is the name of the contstraint
154
+ // Third parameter is the validation function which receives the value of the property
155
+ validator.add('email', 'OnlyGermanMails', async (email: string) {
156
+ if (! email.endsWith('.de')) {
157
+
158
+ // You do not need to set the constraint name nor the property on the misfit.
159
+ // Those will be set automatically.
160
+ return new Misfit
161
+ }
162
+ })
163
+
164
+ // Second parameter is the name of the contstraint
165
+ // Third parameter is the validation function which receives the complete object owning both properties
149
166
  validator.add(['firstName', 'lastName'], 'Different', async (user: User) => {
150
167
  if (user.firstName == user.lastName) {
151
168
  let misfit = new Misfit
152
169
 
153
- // You can skip setting a name and the property(s) for the misfit. These will be set automatically.
170
+ // You do not need to set the constraint name nor the properties on the misfit.
171
+ // Those will be set automatically.
154
172
 
155
- // We give it some information here on what went wrong. What you put in here depends on your needs.
156
- misfit.constraints = {
173
+ // You can provide some contextual information
174
+ misfit.values = {
157
175
  firstName: user.firstName,
158
176
  lastName: user.lastName
159
177
  }
160
178
 
161
- return misfits
179
+ return misfit
162
180
  }
163
181
  })
164
182
  ```
165
183
 
184
+ In the case the misfit involves exactly one property, its corresponding validation function receives the value of that one property as a parameter. In the case the misfit involves more than one property, the corresponding validation function receives the whole object that is being validated, so that all of the involved properties can be accessed.
185
+
166
186
  ### Custom constraints as classes
167
187
 
168
188
  If you want to reuse a constraint over and over again, create a new class for it.
@@ -170,39 +190,29 @@ If you want to reuse a constraint over and over again, create a new class for it
170
190
  ```typescript
171
191
  import { Constraint } from 'knight-validation'
172
192
 
173
- class YourConstraint extends Constraint {
193
+ export interface DifferentMisfitValues {
194
+ firstName: string
195
+ lastName: string
196
+ }
197
+
198
+ export class Different extends Constraint<User, DifferentMisfitValues> {
174
199
 
175
200
  // Override the abstract method validate
176
- async validate(obj: any, properties: string|string[]): Promise<Misfit|undefined> {
201
+ validate(user: User): Promise<Misfit<DifferentMisfitValues>|null> {
202
+ if (user.firstName == user.lastName) {
203
+ let misfit = new Misfit<DifferentMisfitValues>
177
204
 
178
- // At first you want to check if the properties are absent because in case of absense you do not want to validate because a property may be optional.
179
- if (this.arePropertyAbsent(obj, properties)) {
180
- return
205
+ // You do not need to set the constraint name nor the properties on the misfit.
206
+ // Those will be set automatically.
207
+
208
+ misfit.values = {
209
+ firstName: user.firstName,
210
+ lastName: user.lastName
181
211
  }
182
212
 
183
- // Next you need to check if the properties were single or a nultiple ones. Maybe you just implement on of the two possibilities.
184
- if (typeof properties == 'string') {
185
- // In case of a single property
186
- }
187
- else {
188
- // In case of multiple properties
189
- }
213
+ return misfit
190
214
  }
191
215
  }
192
216
  ```
193
217
 
194
- Another possibility is to use the `defaultValidation` method. It will do the check for absence and will implement the validation of combined properties.
195
-
196
- ```typescript
197
- import { Constraint } from 'knight-validation'
198
-
199
- class YourConstraint extends Constraint {
200
- async validate(obj: any, properties: string|string[]): Promise<Misfit|undefined> {
201
- return this.defaultValidation(obj, properties, async (value: any) => {
202
- if (value == 1) { // Validate the value here
203
- return new Misfit
204
- }
205
- })
206
- }
207
- }
208
- ```
218
+ You need to pay attention to the parameter of the validate method. In the case your constraint is assigned to a single property, that parameter will have the value of the mentioned property. In the case your constraint is assigned to an array of properties, that parameter will have the complete object as its value which ought to contain the mentioned properties.
@@ -0,0 +1,6 @@
1
+ export declare class DotNotification {
2
+ properties: string[];
3
+ constructor(dotNotification: string);
4
+ exists(obj: any): boolean;
5
+ get(obj: any): any;
6
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DotNotification = void 0;
4
+ class DotNotification {
5
+ constructor(dotNotification) {
6
+ this.properties = dotNotification.split('.');
7
+ }
8
+ exists(obj) {
9
+ let exists = false;
10
+ for (let property of this.properties) {
11
+ if (typeof obj == 'object' && obj !== null && obj[property] !== undefined) {
12
+ exists = true;
13
+ obj = obj[property];
14
+ }
15
+ else {
16
+ exists = false;
17
+ break;
18
+ }
19
+ }
20
+ return exists;
21
+ }
22
+ get(obj) {
23
+ for (let property of this.properties) {
24
+ if (typeof obj == 'object' && obj !== null) {
25
+ obj = obj[property];
26
+ }
27
+ else {
28
+ obj = undefined;
29
+ break;
30
+ }
31
+ }
32
+ return obj;
33
+ }
34
+ }
35
+ exports.DotNotification = DotNotification;
@@ -3,18 +3,18 @@ import { Misfit } from './Misfit';
3
3
  export interface ValidatorOptions {
4
4
  checkOnlyWhatIsThere?: boolean;
5
5
  }
6
- interface ValidatorEntry {
6
+ interface ValidatorEntry<T = any> {
7
7
  properties: string[];
8
8
  constraint?: Constraint;
9
- validator?: Validator<any>;
10
- condition?: (object: any) => Promise<boolean>;
9
+ validator?: Validator;
10
+ condition?: (object: T) => Promise<boolean>;
11
11
  }
12
- export declare class Validator<T> {
12
+ export declare class Validator<T = any> {
13
13
  options?: ValidatorOptions;
14
- entries: ValidatorEntry[];
14
+ entries: ValidatorEntry<T>[];
15
15
  constructor(options?: ValidatorOptions);
16
- add(properties: string, constraint: Constraint, condition?: (object: T) => Promise<boolean>): void;
17
- add(properties: string, constraintName: string, validate: (value: any) => Promise<Misfit | null>, condition?: (object: T) => Promise<boolean>): void;
16
+ add(property: string, constraint: Constraint<T>, condition?: (object: T) => Promise<boolean>): void;
17
+ add(property: string, constraintName: string, validate: (value: any) => Promise<Misfit | null>, condition?: (object: T) => Promise<boolean>): void;
18
18
  add(properties: string[], constraintName: string, validate: (object: T) => Promise<Misfit | null>, condition?: (object: T) => Promise<boolean>): void;
19
19
  add(property: string, validator: Validator<any>, condition?: (object: T) => Promise<boolean>): void;
20
20
  add(validator: Validator<any>): void;
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.Validator = void 0;
13
13
  const Constraint_1 = require("./Constraint");
14
+ const DotNotification_1 = require("./DotNotification");
14
15
  const QuickConstraint_1 = require("./QuickConstraint");
15
16
  class Validator {
16
17
  constructor(options) {
@@ -42,7 +43,7 @@ class Validator {
42
43
  condition = args.length > 2 ? args[2] : undefined;
43
44
  }
44
45
  else {
45
- throw new Error('Wrong parameters');
46
+ throw new Error('Invalid parameters');
46
47
  }
47
48
  this.entries.push({
48
49
  properties: properties,
@@ -73,7 +74,8 @@ class Validator {
73
74
  }
74
75
  let atLeastOnePropertyExists = false;
75
76
  for (let property of entry.properties) {
76
- if (object[property] !== undefined) {
77
+ let dotNotification = new DotNotification_1.DotNotification(property);
78
+ if (dotNotification.exists(object)) {
77
79
  atLeastOnePropertyExists = true;
78
80
  break;
79
81
  }
@@ -85,7 +87,8 @@ class Validator {
85
87
  let misfit;
86
88
  if (entry.properties.length == 1) {
87
89
  let property = entry.properties[0];
88
- let value = object[property];
90
+ let dotNotification = new DotNotification_1.DotNotification(property);
91
+ let value = dotNotification.get(object);
89
92
  misfit = yield entry.constraint.validate(value);
90
93
  }
91
94
  else {
@@ -95,7 +98,7 @@ class Validator {
95
98
  if (misfit.constraint === undefined) {
96
99
  misfit.constraint = entry.constraint.name;
97
100
  }
98
- misfit.properties = entry.properties;
101
+ misfit.properties = entry.properties.slice();
99
102
  misfittingProperties.push(...entry.properties);
100
103
  misfits.push(misfit);
101
104
  }
@@ -105,8 +108,9 @@ class Validator {
105
108
  throw new Error('Using another validator only works for one property');
106
109
  }
107
110
  let property = entry.properties[0];
108
- let value = object[property];
109
- if (typeof value != 'object' || value === null) {
111
+ let dotNotification = new DotNotification_1.DotNotification(property);
112
+ let value = dotNotification.get(object);
113
+ if (value === undefined) {
110
114
  continue;
111
115
  }
112
116
  if (value instanceof Array) {
@@ -3,8 +3,8 @@ import { Misfit } from '../Misfit';
3
3
  export interface ExistsMisfitValues {
4
4
  notExistingValue: any;
5
5
  }
6
- export declare class Exists extends Constraint<any, ExistsMisfitValues> {
7
- doesExist: (value: any) => Promise<boolean>;
8
- constructor(doesExist: (value: any) => Promise<boolean>);
9
- validate(value: any): Promise<Misfit<ExistsMisfitValues> | null>;
6
+ export declare class Exists<T> extends Constraint<T, ExistsMisfitValues> {
7
+ doesExist: (value: T) => Promise<boolean>;
8
+ constructor(doesExist: (value: T) => Promise<boolean>);
9
+ validate(value: T): Promise<Misfit<ExistsMisfitValues> | null>;
10
10
  }
@@ -3,8 +3,8 @@ import { Misfit } from '../Misfit';
3
3
  export interface UniqueMisfitValues {
4
4
  notUniqueValue: any;
5
5
  }
6
- export declare class Unique extends Constraint<any, UniqueMisfitValues> {
7
- isUnique: (value: any) => Promise<boolean>;
8
- constructor(isUnique: (value: any) => Promise<boolean>);
9
- validate(value: any): Promise<Misfit<UniqueMisfitValues> | null>;
6
+ export declare class Unique<T> extends Constraint<T, UniqueMisfitValues> {
7
+ isUnique: (value: T) => Promise<boolean>;
8
+ constructor(isUnique: (value: T) => Promise<boolean>);
9
+ validate(value: T): Promise<Misfit<UniqueMisfitValues> | null>;
10
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knight-validation",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "description": "A validation lib",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",