Skip to content

Commit 4207f60

Browse files
committed
Add support for custom messages
1 parent e29ed90 commit 4207f60

File tree

3 files changed

+205
-55
lines changed

3 files changed

+205
-55
lines changed

README.md

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,15 @@ You can install it via [NPM](http://npmjs.org/).
4848
```
4949
$ npm install fastest-validator --save
5050
```
51-
or
51+
or
5252
```
5353
$ yarn add fastest-validator
5454
```
5555

5656
## Usage
5757

5858
### Simple method
59-
Call the `validate` method with the `object` and the `schema`.
59+
Call the `validate` method with the `object` and the `schema`.
6060
> If performance is important, you won't use this method.
6161
6262
```js
@@ -76,7 +76,7 @@ console.log(v.validate({ id: 5, name: "John", status: true }, schema));
7676
console.log(v.validate({ id: 5, name: "Al", status: true }, schema));
7777
/* Returns an array with errors:
7878
[
79-
{
79+
{
8080
type: 'stringMin',
8181
expected: 3,
8282
actual: 2,
@@ -111,7 +111,7 @@ console.log(check({ id: 5, name: "John", status: true }));
111111
console.log(check({ id: 2, name: "Adam" }));
112112
/* Returns an array with errors:
113113
[
114-
{
114+
{
115115
type: 'required',
116116
field: 'status',
117117
message: 'The \'status\' field is required!'
@@ -187,7 +187,7 @@ v.validate({ prop: "John" }, schema); // Valid
187187
```
188188

189189
## `array`
190-
This is an `Array` validator.
190+
This is an `Array` validator.
191191

192192
**Simple example with strings:**
193193
```js
@@ -226,7 +226,7 @@ let schema = {
226226
} }
227227
}
228228

229-
v.validate({
229+
v.validate({
230230
users: [
231231
{ id: 1, name: "John", status: true },
232232
{ id: 2, name: "Jane", status: true },
@@ -259,7 +259,7 @@ v.validate({ roles: ["guest"] }, schema); // Fail
259259

260260

261261
## `boolean`
262-
This is a `Boolean` validator.
262+
This is a `Boolean` validator.
263263

264264
```js
265265
let schema = {
@@ -278,7 +278,7 @@ Property | Default | Description
278278

279279

280280
## `date`
281-
This is a `Date` validator.
281+
This is a `Date` validator.
282282

283283
```js
284284
let schema = {
@@ -295,7 +295,7 @@ Property | Default | Description
295295
`convert` | `false`| if `true` and the type is not `Date`, try to convert with `new Date()`.
296296

297297
## `email`
298-
This is an e-mail address validator.
298+
This is an e-mail address validator.
299299

300300
```js
301301
let schema = {
@@ -313,7 +313,7 @@ Property | Default | Description
313313
`mode` | `quick` | Checker method. Can be `quick` or `precise`.
314314

315315
## `enum`
316-
This is an enum validator.
316+
This is an enum validator.
317317

318318
```js
319319
let schema = {
@@ -332,7 +332,7 @@ Property | Default | Description
332332

333333

334334
## `forbidden`
335-
This validator returns an error if the property exists in the object.
335+
This validator returns an error if the property exists in the object.
336336

337337
```js
338338
let schema = {
@@ -393,15 +393,15 @@ let schema = {
393393
} }
394394
}
395395

396-
v.validate({
396+
v.validate({
397397
address: {
398398
country: "Italy",
399399
city: "Rome",
400400
zip: 12345
401-
}
401+
}
402402
}, schema); // Valid
403403

404-
v.validate({
404+
v.validate({
405405
address: {
406406
country: "Italy",
407407
city: "Rome"
@@ -440,7 +440,7 @@ Property | Default | Description
440440

441441

442442
## `url`
443-
This is an URL validator.
443+
This is an URL validator.
444444

445445
```js
446446
let schema = {
@@ -502,9 +502,9 @@ let v = new Validator({
502502

503503
const schema = {
504504
name: { type: "string", min: 3, max: 255 },
505-
weight: {
506-
type: "custom",
507-
minWeight: 10,
505+
weight: {
506+
type: "custom",
507+
minWeight: 10,
508508
check(value, schema) {
509509
return (value < schema.minWeight)
510510
? this.makeError("weightMin", schema.minWeight, value)
@@ -518,12 +518,12 @@ console.log(v.validate({ name: "John", weight: 50 }, schema));
518518

519519
console.log(v.validate({ name: "John", weight: 8 }, schema));
520520
/* Returns an array with errors:
521-
[{
522-
type: 'weightMin',
523-
expected: 10,
524-
actual: 8,
525-
field: 'weight',
526-
message: 'The weight must be greater than 10! Actual: 8'
521+
[{
522+
type: 'weightMin',
523+
expected: 10,
524+
actual: 8,
525+
field: 'weight',
526+
message: 'The weight must be greater than 10! Actual: 8'
527527
}]
528528
*/
529529
```
@@ -542,18 +542,61 @@ const v = new Validator({
542542

543543
v.validate({ name: "John" }, { name: { type: "string", min: 6 }});
544544
/* Returns:
545-
[
546-
{
545+
[
546+
{
547547
type: 'stringMin',
548548
expected: 6,
549549
actual: 4,
550550
field: 'name',
551-
message: 'A(z) \'name\' mező túl rövid. Minimum: 6, Jelenleg: 4'
552-
}
551+
message: 'A(z) \'name\' mező túl rövid. Minimum: 6, Jelenleg: 4'
552+
}
553553
]
554554
*/
555555
```
556+
# Personalised Messages
557+
Sometimes the standard messages are too generic. You can customise messages per validation type per field:
556558

559+
```js
560+
const Validator = require("fastest-validator");
561+
const v = new Validator();
562+
const schema = {
563+
firstname: {
564+
type: "string",
565+
min: 6,
566+
messages: {
567+
string: "Please check your firstname",
568+
stringMin: "Your firstname is too short"
569+
}
570+
},
571+
lastname: {
572+
type: "string",
573+
min: 6,
574+
messages: {
575+
string: "Please check your lastname",
576+
stringMin: "Your lastname is too short"
577+
}
578+
}
579+
}
580+
v.validate({ firstname: "John", lastname: 23 }, schema );
581+
/* Returns:
582+
[
583+
{
584+
type: 'stringMin',
585+
expected: 6,
586+
actual: 4,
587+
field: 'firstname',
588+
message: 'Your firstname is too short'
589+
},
590+
{
591+
type: 'string',
592+
expected: undefined,
593+
actual: undefined,
594+
field: 'lastname',
595+
message: 'Please check your lastname'
596+
}
597+
]
598+
*/
599+
```
557600
## Message types
558601
Name | Default text
559602
------------------- | -------------

lib/validator.js

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,9 @@ function escapeEvalString(str) {
4242
return "\\n";
4343
case "\r":
4444
return "\\r";
45-
case "
46-
":
45+
case "\u2028":
4746
return "\\u2028";
48-
case "
49-
":
47+
case "\u2029":
5048
return "\\u2029";
5149
}
5250
});
@@ -126,7 +124,6 @@ Validator.prototype.compileSchemaObject = function(schemaObject) {
126124
}
127125

128126
compiledObject.properties = Object.keys(schemaObject).map(name => {
129-
130127
const compiledType = this.compileSchemaType(schemaObject[name]);
131128
return { name: name, compiledType: compiledType };
132129
});
@@ -147,7 +144,11 @@ Validator.prototype.compileSchemaObject = function(schemaObject) {
147144
sourceCode.push(`res = this.checkSchemaRule(${propertyValueExpr}, properties[${i}].compiledType, propertyPath, value);`);
148145
}
149146
sourceCode.push("if (res !== true) {");
150-
sourceCode.push("\tthis.handleResult(errors, propertyPath, res);");
147+
sourceCode.push(" let customMsg = false;");
148+
sourceCode.push(` if (properties[${i}].compiledType.messages && properties[${i}].compiledType.messages[res.type]) {`);
149+
sourceCode.push(` customMsg = properties[${i}].compiledType.messages[res.type];`);
150+
sourceCode.push(" }");
151+
sourceCode.push("\t this.handleResult(errors, propertyPath, res, customMsg);");
151152
sourceCode.push("}");
152153
}
153154

@@ -159,7 +160,6 @@ Validator.prototype.compileSchemaObject = function(schemaObject) {
159160
};
160161

161162
Validator.prototype.compileSchemaType = function(schemaType) {
162-
163163
if (Array.isArray(schemaType)) {
164164
// Multiple rules, flatten to array of compiled SchemaRule
165165
const rules = flatten(schemaType.map(r => this.compileSchemaType(r)));
@@ -196,19 +196,11 @@ Validator.prototype.compileSchemaRule = function(schemaRule) {
196196
dataFunction = this.checkSchemaArray;
197197
}
198198

199-
let errorMessage = false;
200-
if (schemaRule.messages[schemaRule.type]) {
201-
errorMessage = schemaRule.messages[schemaRule.type];
202-
} else if (this.messages[schemaObject[name].type]) {
203-
errorMessage = this.messages[schemaRule.type];
204-
}
205-
206199
return {
207200
schemaRule: schemaRule,
208201
ruleFunction: ruleFunction,
209202
dataFunction: dataFunction,
210-
dataParameter: dataParameter,
211-
errorMessage
203+
dataParameter: dataParameter
212204
};
213205
};
214206

@@ -258,7 +250,7 @@ Validator.prototype.checkSchemaType = function(value, compiledType, path, parent
258250
const res = this.checkSchemaRule(value, compiledType[i], path, parent);
259251

260252
if (res !== true) {
261-
this.handleResult(errors, path, res, compiledType[i].errorMessage);
253+
this.handleResult(errors, path, res);
262254
} else {
263255
// Jump out after first success and clear previous errors
264256
return true;
@@ -298,14 +290,25 @@ Validator.prototype.checkSchemaRule = function(value, compiledRule, path, parent
298290
return true;
299291

300292
const errors = [];
301-
this.handleResult(errors, path, this.makeError("required"), schemaRule.errorMessage);
293+
let customMsg = false;
294+
if (schemaRule.messages && schemaRule.messages["required"]) {
295+
customMsg = schemaRule.messages["required"];
296+
}
297+
this.handleResult(errors, path, this.makeError("required"), customMsg);
298+
302299
return errors;
303300
}
304301

305302
const res = compiledRule.ruleFunction.call(this, value, schemaRule, path, parent);
306303
if (res !== true) {
307304
const errors = [];
308-
this.handleResult(errors, path, res, schemaRule.errorMessage);
305+
306+
let customMsg = false;
307+
if (schemaRule.messages && schemaRule.messages[res.type]) {
308+
customMsg = schemaRule.messages[res.type];
309+
}
310+
this.handleResult(errors, path, res, customMsg);
311+
309312
return errors;
310313
}
311314

@@ -323,7 +326,7 @@ Validator.prototype.checkSchemaRule = function(value, compiledRule, path, parent
323326
* @param {String} fieldPath
324327
* @param {Array|Object} res
325328
*/
326-
Validator.prototype.handleResult = function(errors, fieldPath, res, errorMessage = false) {
329+
Validator.prototype.handleResult = function(errors, fieldPath, res, customMsg = false) {
327330
let items;
328331
if (!Array.isArray(res))
329332
items = [res];
@@ -334,7 +337,7 @@ Validator.prototype.handleResult = function(errors, fieldPath, res, errorMessage
334337
if (!err.field)
335338
err.field = fieldPath;
336339
if (!err.message)
337-
err.message = this.resolveMessage(err, errorMessage);
340+
err.message = this.resolveMessage(err, customMsg);
338341

339342
errors.push(err);
340343
});
@@ -360,13 +363,16 @@ Validator.prototype.makeError = function(type, expected, actual) {
360363
*
361364
* @param {Object} err Validation error object
362365
*/
363-
Validator.prototype.resolveMessage = function(err, msg = '') {
366+
Validator.prototype.resolveMessage = function(err, msg = false) {
364367

365-
if (typeof msg == "string") {
366-
const expected = err.expected != null ? err.expected : "";
367-
const actual = err.actual != null ? err.actual : "";
368-
return msg.replace(/\{field\}/g, err.field).replace(/\{expected\}/g, expected).replace(/\{actual\}/g, actual);
369-
}
368+
if (typeof msg != "string")
369+
msg = this.messages[err.type];
370+
371+
if (msg != null) {
372+
const expected = err.expected != null ? err.expected : "";
373+
const actual = err.actual != null ? err.actual : "";
374+
return msg.replace(/\{field\}/g, err.field).replace(/\{expected\}/g, expected).replace(/\{actual\}/g, actual);
375+
}
370376
};
371377

372378
/**

0 commit comments

Comments
 (0)