Skip to content

Commit aa91e01

Browse files
author
Umed Khudoiberdiev
committed
added more flexible way to use message functions
1 parent 0d4cab4 commit aa91e01

File tree

5 files changed

+112
-73
lines changed

5 files changed

+112
-73
lines changed

sample/sample5-schemas/post.json

+47-61
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,52 @@
11
{
22
"name": "post",
33
"properties": {
4-
"title": [
5-
{
6-
"type": "min_length",
7-
"value1": 10
8-
},
9-
{
10-
"type": "max_length",
11-
"value1": 20
12-
}
13-
],
14-
"text": [
15-
{
16-
"type": "contains",
17-
"value1": "hello"
18-
}
19-
],
20-
"rating": [
21-
{
22-
"type": "is_int"
23-
}
24-
],
25-
"email": [
26-
{
27-
"type": "is_email"
28-
}
29-
],
30-
"site": [
31-
{
32-
"type": "is_fqdn"
33-
}
34-
],
35-
"createDate": [
36-
{
37-
"type": "is_date"
38-
}
39-
],
40-
"tags": [
41-
{
42-
"type": "array_not_empty"
43-
},
44-
{
45-
"type": "array_min_size",
46-
"value1": 2
47-
},
48-
{
49-
"type": "array_max_size",
50-
"value1": 5
51-
},
52-
{
53-
"type": "min_length",
54-
"each": true,
55-
"value1": 3,
56-
"message": "Tag is too short. Minimal length is $value characters"
57-
},
58-
{
59-
"type": "max_length",
60-
"each": true,
61-
"value1": 50,
62-
"message": "Tag is too long. Maximal length is $value characters"
63-
}
64-
]
4+
"title": [{
5+
"type": "min_length",
6+
"constraints": [10]
7+
},
8+
{
9+
"type": "max_length",
10+
"constraints": [20]
11+
}],
12+
"text": [{
13+
"type": "contains",
14+
"value1": "hello"
15+
}],
16+
"rating": [{
17+
"type": "is_int"
18+
}],
19+
"email": [{
20+
"type": "is_email"
21+
}],
22+
"site": [{
23+
"type": "is_fqdn"
24+
}],
25+
"createDate": [{
26+
"type": "is_date"
27+
}],
28+
"tags": [{
29+
"type": "array_not_empty"
30+
},
31+
{
32+
"type": "array_min_size",
33+
"constraints": [2]
34+
},
35+
{
36+
"type": "array_max_size",
37+
"constraints": [5]
38+
},
39+
{
40+
"type": "min_length",
41+
"each": true,
42+
"constraints": [3],
43+
"message": "Tag is too short. Minimal length is $value characters"
44+
},
45+
{
46+
"type": "max_length",
47+
"each": true,
48+
"constraints": [50],
49+
"message": "Tag is too long. Maximal length is $value characters"
50+
}]
6551
}
6652
}

src/metadata/ValidationMetadata.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {ValidationMetadataArgs} from "./ValidationMetadataArgs";
2+
import {MessageArguments} from "../validation/MessageArguments";
23

34
/**
45
* This metadata contains validation rules.
@@ -37,7 +38,7 @@ export class ValidationMetadata {
3738
/**
3839
* Validation message to be shown in the case of error.
3940
*/
40-
message: string|((value?: any, constraints?: any[]) => string);
41+
message: string|((args: MessageArguments) => string);
4142

4243
/**
4344
* Validation groups used for this validation.

src/validation/MessageArguments.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Arguments being sent to message builders - user can create message either by simply returning a string,
3+
* either by returning a function that accepts MessageArguments and returns a message string built based on these arguments.
4+
*/
5+
export interface MessageArguments {
6+
7+
/**
8+
* Validating value.
9+
*/
10+
value: any;
11+
12+
/**
13+
* Constraints set by this validation type.
14+
*/
15+
constraints: any[];
16+
17+
/**
18+
* Name of the target that is being validated.
19+
*/
20+
targetName: string;
21+
22+
/**
23+
* Object that is being validated.
24+
*/
25+
object: Object;
26+
27+
/**
28+
* Name of the object's property being validated.
29+
*/
30+
property: string;
31+
32+
}

src/validation/ValidationExecutor.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {ValidatorOptions} from "./ValidatorOptions";
77
import {ValidationTypes} from "./ValidationTypes";
88
import {ValidatorConstraintInterface} from "./ValidatorConstraintInterface";
99
import {ConstraintMetadata} from "../metadata/ConstraintMetadata";
10+
import {MessageArguments} from "./MessageArguments";
1011

1112
/**
1213
* Executes validation over given object.
@@ -146,14 +147,23 @@ export class ValidationExecutor {
146147

147148
let messageString: string;
148149
if (message instanceof Function) {
149-
messageString = (message as ((value?: any, constraints?: any[]) => string))(value, metadata.constraints);
150+
const messageArgs: MessageArguments = {
151+
targetName: targetName,
152+
property: metadata.propertyName,
153+
object: target,
154+
value: value,
155+
constraints: metadata.constraints
156+
};
157+
messageString = (message as (args: MessageArguments) => string)(messageArgs);
150158

151159
} else if (typeof message === "string") {
152160
messageString = message as string;
153161
}
154162

155163
if (messageString && metadata.constraints instanceof Array)
156-
metadata.constraints.forEach((constraint, index) => messageString.replace(new RegExp(`\$constraint${index}`, "g"), constraint));
164+
metadata.constraints.forEach((constraint, index) => {
165+
messageString = messageString.replace(new RegExp(`\\$constraint${index + 1}`, "g"), constraint);
166+
});
157167
if (messageString && value !== undefined && value !== null)
158168
messageString = messageString.replace(/\$value/g, value);
159169
if (messageString)

src/validation/ValidationTypes.ts

+19-9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {MessageArguments} from "./MessageArguments";
12
/**
23
* Validation types.
34
*/
@@ -94,14 +95,14 @@ export class ValidationTypes {
9495
/**
9596
* Gets default validation error message for the given validation type.
9697
*/
97-
static getMessage(type: string): string|((value?: any, constraints?: any[]) => string) {
98+
static getMessage(type: string): string|((args: MessageArguments) => string) {
9899
switch (type) {
99100

100101
/* common checkers */
101102
case this.EQUALS:
102-
return "given value ($value) of $property is not equal to $constraint1";
103+
return "$property must be equal to $constraint1";
103104
case this.NOT_EQUALS:
104-
return "given value ($value) of $property should not be equal to $constraint1";
105+
return "$property should not be equal to $constraint1";
105106
case this.EMPTY:
106107
return "$property must be empty";
107108
case this.NOT_EMPTY:
@@ -130,6 +131,8 @@ export class ValidationTypes {
130131
return "$property must be divisible by $constraint1";
131132
case this.IS_POSITIVE:
132133
return "$property must be a positive number";
134+
case this.IS_NEGATIVE:
135+
return "$property must be a negative number";
133136
case this.GREATER_THEN:
134137
return "$property must be greater then $constraint1";
135138
case this.LESS_THEN:
@@ -147,7 +150,7 @@ export class ValidationTypes {
147150
case this.IS_DATE_STRING:
148151
return "$property must be a date string";
149152
case this.IS_NUMBER_STRING:
150-
return "$property must be a number";
153+
return "$property must be a number string";
151154

152155
/* string checkers */
153156
case this.CONTAINS:
@@ -209,15 +212,22 @@ export class ValidationTypes {
209212
case this.IS_UPPERCASE:
210213
return "$property must be uppercase";
211214
case this.LENGTH:
212-
return () => { // todo
215+
return (args: MessageArguments) => { // todo more complex object must come here (with target and propertyName)
216+
const isMinLength = args.constraints[0] !== null && args.constraints[0] !== undefined;
217+
const isMaxLength = args.constraints[1] !== null && args.constraints[1] !== undefined;
218+
if (isMinLength && (!args.value || args.value.length < args.constraints[0])) {
219+
return "$property must be longer then $constraint1";
220+
} else if (isMaxLength && (args.value.length > args.constraints[1])) {
221+
return "$property must be shorter then $constraint2";
222+
}
213223
return "$property must be longer then $constraint1 and shorter then $constraint2";
214224
};
215225
case this.MIN_LENGTH:
216226
return "$property must be longer then $constraint1";
217227
case this.MAX_LENGTH:
218228
return "$property must be shorter then $constraint2";
219229
case this.MATCHES:
220-
return "$property must much a given regular expression $constraint1";
230+
return "$property must match $constraint1 regular expression";
221231

222232
/* array checkers */
223233
case this.ARRAY_CONTAINS:
@@ -227,11 +237,11 @@ export class ValidationTypes {
227237
case this.ARRAY_NOT_EMPTY:
228238
return "$property should not be empty";
229239
case this.ARRAY_MIN_SIZE:
230-
return "$property's must contain at least $constraint1 elements";
240+
return "$property must contain at least $constraint1 elements";
231241
case this.ARRAY_MAX_SIZE:
232-
return "$property's must contain not more then $constraint1 elements";
242+
return "$property must contain not more then $constraint1 elements";
233243
case this.ARRAY_UNIQUE:
234-
return "all $property's elements must be unqiue";
244+
return "All $property's elements must be unique";
235245
}
236246
}
237247

0 commit comments

Comments
 (0)