@ssense/restify-request-validator
Advanced tools
Comparing version 1.0.11 to 1.0.12
@@ -14,4 +14,19 @@ "use strict"; | ||
}; | ||
RequestValidator.prototype.getErrorMessage = function (field, errorType, defaultMessage) { | ||
if (this.customErrorMessages.hasOwnProperty(field) && this.customErrorMessages[field].hasOwnProperty(errorType)) { | ||
return this.customErrorMessages[field][errorType]; | ||
} | ||
return defaultMessage; | ||
}; | ||
RequestValidator.prototype.hasCustomErrorMessages = function () { | ||
return Object.keys(this.customErrorMessages).length > 0; | ||
}; | ||
RequestValidator.prototype.validate = function (req, res, next) { | ||
if (req.hasOwnProperty('route') && req.route.hasOwnProperty('validation')) { | ||
if (req.route.hasOwnProperty('validationMessages')) { | ||
this.customErrorMessages = req.route.validationMessages; | ||
} | ||
else { | ||
this.customErrorMessages = {}; | ||
} | ||
var errorMessages = []; | ||
@@ -77,3 +92,3 @@ if (req.route.validation.hasOwnProperty('url')) { | ||
if (paramValidation.required === true && (!input || type === 'undefined')) { | ||
errorMessages = errorMessages.concat("Param " + key + " is required"); | ||
errorMessages = errorMessages.concat(this.getErrorMessage(key, 'required', "Param " + key + " is required")); | ||
} | ||
@@ -99,3 +114,3 @@ if (input) { | ||
if (RequestValidator.checkType(typeValidation) !== true) { | ||
errorMessages.push("Param " + key + " has invalid type (" + paramValidation.type + ")"); | ||
errorMessages.push(this.getErrorMessage(key, 'type', "Param " + key + " has invalid type (" + paramValidation.type + ")")); | ||
} | ||
@@ -108,18 +123,18 @@ input[key] = typeValidation.value; | ||
&& RequestValidator.checkArrayType(input[key], paramValidation.arrayType) !== true) { | ||
errorMessages.push("Param " + key + " has invalid content type (" + paramValidation.arrayType + "[])"); | ||
errorMessages.push(this.getErrorMessage(key, 'arrayType', "Param " + key + " has invalid content type (" + paramValidation.arrayType + "[])")); | ||
} | ||
if (RequestValidator.checkLength(input[key], paramValidation.length) !== true) { | ||
errorMessages.push("Param " + key + " must have a length of " + paramValidation.length); | ||
errorMessages.push(this.getErrorMessage(key, 'length', "Param " + key + " must have a length of " + paramValidation.length)); | ||
} | ||
if (RequestValidator.checkMin(input[key], paramValidation.min) !== true) { | ||
errorMessages.push("Param " + key + " must have a minimum length of " + paramValidation.min); | ||
errorMessages.push(this.getErrorMessage(key, 'min', "Param " + key + " must have a minimum length of " + paramValidation.min)); | ||
} | ||
if (RequestValidator.checkMax(input[key], paramValidation.max) !== true) { | ||
errorMessages.push("Param " + key + " must have a maximum length of " + paramValidation.max); | ||
errorMessages.push(this.getErrorMessage(key, 'max', "Param " + key + " must have a maximum length of " + paramValidation.max)); | ||
} | ||
if (RequestValidator.checkValues(input[key], paramValidation.values) !== true) { | ||
errorMessages.push("Param " + key + " must belong to [" + paramValidation.values.toString() + "]"); | ||
errorMessages.push(this.getErrorMessage(key, 'values', "Param " + key + " must belong to [" + paramValidation.values.toString() + "]")); | ||
} | ||
if (paramValidation.regex && !paramValidation.regex.test(input[key])) { | ||
errorMessages.push("Param " + key + " must match regex " + paramValidation.regex); | ||
errorMessages.push(this.getErrorMessage(key, 'regex', "Param " + key + " must match regex " + paramValidation.regex)); | ||
} | ||
@@ -126,0 +141,0 @@ return errorMessages; |
{ | ||
"name": "@ssense/restify-request-validator", | ||
"version": "1.0.11", | ||
"version": "1.0.12", | ||
"description": "Restify requests validator", | ||
@@ -5,0 +5,0 @@ "main": "js/index.js", |
@@ -122,2 +122,31 @@ # Restify request validator | ||
#### Custom error messages | ||
##### Example usage | ||
You can pass custom error messages via the `validationMessages` param of the route: | ||
```js | ||
function respond(req, res, next) { | ||
res.send('hello ' + req.params.name); | ||
next(); | ||
} | ||
server.get({ | ||
url: '/hello/:name', | ||
validation: { | ||
url: { | ||
name: {type: 'string', required: true, min: 3}, | ||
}, | ||
}, | ||
validationMessages: { | ||
name: { | ||
type: 'The name must be a string', | ||
required: 'The name is required', | ||
min: 'The name must have a minimum length of 3 characters' | ||
} | ||
}, | ||
}, respond); | ||
``` | ||
#### Behavior | ||
@@ -124,0 +153,0 @@ |
@@ -345,2 +345,102 @@ import {expect} from 'chai'; | ||
}); | ||
describe('Custom Error Messages', () => { | ||
it('required', () => { | ||
expected = 'The name is required'; | ||
validator.validate({ | ||
route: { | ||
validation: { | ||
url: { | ||
name: {type: 'string', required: true, min: 3}, | ||
}, | ||
}, | ||
validationMessages: { | ||
name: { | ||
type: 'The name must be a string', | ||
required: 'The name is required', | ||
min: 'The name must have a minimum length of 3 characters' | ||
} | ||
}, | ||
}, url: { | ||
name: '' | ||
} | ||
}, null, test); | ||
}); | ||
it('arrayType', () => { | ||
expected = 'Categories must be an array of numbers'; | ||
validator.validate({ | ||
route: { | ||
validation: { | ||
query: { | ||
categories: {type: 'array', required: true, arrayType: 'number'} | ||
} | ||
}, | ||
validationMessages: { | ||
categories: { | ||
arrayType: 'Categories must be an array of numbers' | ||
} | ||
} | ||
}, query: { | ||
categories: '2,a' | ||
} | ||
}, null, test); | ||
}); | ||
it('regex', () => { | ||
expected = 'Website must start with http://'; | ||
validator.validate({ | ||
route: { | ||
validation: { | ||
body: { | ||
website: {type: 'string', required: true, regex: /^http:\/\//} | ||
} | ||
}, | ||
validationMessages: { | ||
website: { | ||
regex: 'Website must start with http://' | ||
} | ||
} | ||
}, params: { | ||
website: 'test' | ||
} | ||
}, null, test); | ||
}); | ||
it('min/max/length/values with failOnFirstError=false', () => { | ||
validator.disableFailOnFirstError(); | ||
expected = 'Description must have a length >= 2\nSEO Keyword must have a length <= 2\nDesigners must have a length = 2\nDesigners must be either 1 or 2'; | ||
validator.validate({ | ||
route: { | ||
validation: { | ||
query: { | ||
id: {type: 'numeric', required: true, length: 3}, | ||
name: {type: 'string', required: false, length: 4}, | ||
description: {type: 'string', required: true, min: 2}, | ||
seo_keyword: {type: 'string', required: true, max: 2}, | ||
designers: {type: 'array', required: true, length: 2, values: ['1', '2']} | ||
} | ||
}, | ||
validationMessages: { | ||
description: { | ||
min: 'Description must have a length >= 2', | ||
}, | ||
seo_keyword: { | ||
max: 'SEO Keyword must have a length <= 2', | ||
}, | ||
designers: { | ||
length: 'Designers must have a length = 2', | ||
values: 'Designers must be either 1 or 2' | ||
} | ||
} | ||
}, query: { | ||
id: '3456', | ||
description: 'a', | ||
seo_keyword: 'abcd', | ||
designers: '1,3,9', | ||
}, | ||
}, null, test); | ||
}); | ||
}); | ||
}); |
@@ -12,5 +12,11 @@ import {ParamValidation} from './ParamValidation'; | ||
interface ErrorMessage { | ||
message: string; | ||
isCustom: boolean; | ||
} | ||
export class RequestValidator { | ||
private errorHandler: any; | ||
private failOnFirstError: boolean = true; | ||
private customErrorMessages: any; | ||
@@ -25,8 +31,28 @@ constructor(errorHandler: any = Error) { | ||
protected getErrorMessage(field: string, errorType: string, defaultMessage: string): ErrorMessage { | ||
if (this.customErrorMessages.hasOwnProperty(field) && this.customErrorMessages[field].hasOwnProperty(errorType)) { | ||
return { | ||
message: this.customErrorMessages[field][errorType], | ||
isCustom: true | ||
}; | ||
} | ||
return { | ||
message: defaultMessage, | ||
isCustom: false | ||
}; | ||
} | ||
public validate(req: any, res: any, next: Function): void { | ||
if (req.hasOwnProperty('route') && req.route.hasOwnProperty('validation')) { | ||
if (req.route.hasOwnProperty('validationMessages')) { | ||
this.customErrorMessages = req.route.validationMessages; | ||
} else { | ||
this.customErrorMessages = {}; | ||
} | ||
let errorMessages: string[] = []; | ||
if (req.route.validation.hasOwnProperty('url')) { | ||
errorMessages = errorMessages.concat( | ||
this.validateFields(req.params, req.route.validation.url, true).map(msg => `Url: ${msg}`) | ||
this.validateFields(req.params, req.route.validation.url, true) | ||
.map(msg => msg.isCustom ? msg.message : `Url: ${msg.message}`) | ||
); | ||
@@ -36,3 +62,4 @@ } | ||
errorMessages = errorMessages.concat( | ||
this.validateFields(req.query, req.route.validation.query, true).map(msg => `Query: ${msg}`) | ||
this.validateFields(req.query, req.route.validation.query, true) | ||
.map(msg => msg.isCustom ? msg.message : `Query: ${msg.message}`) | ||
); | ||
@@ -42,3 +69,4 @@ } | ||
errorMessages = errorMessages.concat( | ||
this.validateFields(req.params, req.route.validation.body, false).map(msg => `Body: ${msg}`) | ||
this.validateFields(req.params, req.route.validation.body, false) | ||
.map(msg => msg.isCustom ? msg.message : `Body: ${msg.message}`) | ||
); | ||
@@ -105,5 +133,5 @@ } | ||
private validateFields(input: any, validation: any, inUrl: boolean): string[] { | ||
private validateFields(input: any, validation: any, inUrl: boolean): ErrorMessage[] { | ||
if (validation) { | ||
let errorMessages: string[] = []; | ||
let errorMessages: ErrorMessage[] = []; | ||
@@ -116,3 +144,5 @@ for (const key of Object.keys(validation)) { | ||
if (paramValidation.required === true && (!input || type === 'undefined')) { | ||
errorMessages = errorMessages.concat(`Param ${key} is required`); | ||
errorMessages = errorMessages.concat( | ||
this.getErrorMessage(key, 'required', `Param ${key} is required`) | ||
); | ||
} | ||
@@ -140,4 +170,4 @@ | ||
private validateField(input: any, key: any, type: any, paramValidation: any): string[] { | ||
const errorMessages: string[] = []; | ||
private validateField(input: any, key: any, type: any, paramValidation: any): ErrorMessage[] { | ||
const errorMessages: ErrorMessage[] = []; | ||
@@ -147,3 +177,5 @@ // Check type | ||
if (RequestValidator.checkType(typeValidation) !== true) { | ||
errorMessages.push(`Param ${key} has invalid type (${paramValidation.type})`); | ||
errorMessages.push( | ||
this.getErrorMessage(key, 'type', `Param ${key} has invalid type (${paramValidation.type})`) | ||
); | ||
} | ||
@@ -160,3 +192,5 @@ input[key] = typeValidation.value; | ||
&& RequestValidator.checkArrayType(input[key], paramValidation.arrayType) !== true) { | ||
errorMessages.push(`Param ${key} has invalid content type (${paramValidation.arrayType}[])`); | ||
errorMessages.push( | ||
this.getErrorMessage(key, 'arrayType', `Param ${key} has invalid content type (${paramValidation.arrayType}[])`) | ||
); | ||
} | ||
@@ -166,3 +200,5 @@ | ||
if (RequestValidator.checkLength(input[key], paramValidation.length) !== true) { | ||
errorMessages.push(`Param ${key} must have a length of ${paramValidation.length}`); | ||
errorMessages.push( | ||
this.getErrorMessage(key, 'length', `Param ${key} must have a length of ${paramValidation.length}`) | ||
); | ||
} | ||
@@ -172,3 +208,5 @@ | ||
if (RequestValidator.checkMin(input[key], paramValidation.min) !== true) { | ||
errorMessages.push(`Param ${key} must have a minimum length of ${paramValidation.min}`); | ||
errorMessages.push( | ||
this.getErrorMessage(key, 'min', `Param ${key} must have a minimum length of ${paramValidation.min}`) | ||
); | ||
} | ||
@@ -178,3 +216,5 @@ | ||
if (RequestValidator.checkMax(input[key], paramValidation.max) !== true) { | ||
errorMessages.push(`Param ${key} must have a maximum length of ${paramValidation.max}`); | ||
errorMessages.push( | ||
this.getErrorMessage(key, 'max', `Param ${key} must have a maximum length of ${paramValidation.max}`) | ||
); | ||
} | ||
@@ -184,3 +224,5 @@ | ||
if (RequestValidator.checkValues(input[key], paramValidation.values) !== true) { | ||
errorMessages.push(`Param ${key} must belong to [${paramValidation.values.toString()}]`); | ||
errorMessages.push( | ||
this.getErrorMessage(key, 'values', `Param ${key} must belong to [${paramValidation.values.toString()}]`) | ||
); | ||
} | ||
@@ -190,3 +232,5 @@ | ||
if (paramValidation.regex && !paramValidation.regex.test(input[key])) { | ||
errorMessages.push(`Param ${key} must match regex ${paramValidation.regex}`); | ||
errorMessages.push( | ||
this.getErrorMessage(key, 'regex', `Param ${key} must match regex ${paramValidation.regex}`) | ||
); | ||
} | ||
@@ -193,0 +237,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
61645
1013
217
19