Validator
An easy to use, promise based constraint based constraint validation package inspired by the Symfony framework
Installation
Install the package with npm install @smayas/validator
Usage
Basic value validation
import { Validator, ConstraintViolationInterface } from "@smayas/validator";
import * as Constraint from "@smayas/validator/dist/constraints";
const validator = new Validator();
// validating an e-mail value
const value = 'some@invalid';
const constraint = new Constraint.Email({
message: 'This e-mail "%{value}" does not seem to be valid'
});
const promise = validator.validate(value, constraint);
promise.then(function(violations: ConstraintViolationInterface[]) {
if(violations.length > 0) {
return console.log(violations[0].message);
}
return console.log(`The e-mail ${value} is a valid e-mail address`);
});
Object graph validation
In addition to simple value validation, object graphs can be validated as well.
import { Validator, ConstraintViolationInterface } from "@smayas/validator";
import * as Constraint from "@smayas/validator/dist/constraints";
// creating the validator instance
const validator = new Validator();
// an imaginary user object
const user = {
name: 'Bruce Wayne',
email: 'bruce.wayne@wayneenterprises.com',
age: 55
}
// declaring the validation schema
const validationSchema = {
name: [
new Constraint.NotBlank({
message: "The user's name cannot be blank"
})
],
email: [
new Constraint.NotBlank({
message: "The e-mail address cannot be blank"
}),
new Constraint.Email({
message: "The e-mail address does not seem to be valid"
})
],
age: [
new Constraint.NotBlank({
message: "User's age cannot be blank",
}),
new Constraint.Range({
min: 20,
max: 50,
minMessage: "The user must be between 25 and 50 years of age"
})
]
};
// validating the object
const promise = validator.validate(user, validationSchema);
// handling violations if present
promise.then(function(violations: ConstraintViolationInterface[]) {
if(violations.length > 0) {
return console.log(violations);
}
console.log("User is valid");
});
Validation groups
Validation groups are useful when you want to validate only certain properties of an object and not the entire object. By design, all constraint validation groups default to a global 'Default' one.
import { Validator, ConstraintViolationInterface } from "@smayas/validator";
import * as Constraint from "@smayas/validator/dist/constraints";
const validator = new Validator();
const user = {
email: 'bruce.wayne@wayneenterprises.com',
age: ''
}
const validationSchema = {
email: [
new Constraint.NotBlank({
message: "User's e-mail cannot be blank",
groups: ['Default', 'email']
}),
new Constraint.NotBlank({
message: "Invalid user e-mail provided",
groups: ['Default', 'email']
}),
],
age: [
new Constraint.NotBlank({
message: "User's age cannot be blank",
})
]
};
const promise = validator.validate(user, validationSchema, ['email']);
promise.then(function(violations: ConstraintViolationInterface[]) {
if(violations.length > 0) {
return console.log(violations);
}
console.log("User is valid");
});
Array validation
A specific constraint called All is in charge of validating each element of a provided array
import { Validator, ConstraintViolationInterface } from "@smayas/validator";
import * as Constraint from "@smayas/validator/dist/constraints";
const validator = new Validator();
const tags = ['music', 'business', false, 'entertainment']
const constraint = new Constraint.All({
constraints: [new Constraint.NotBlank({
message: 'Element at index %{_index} is blank'
})]
});
// passing only the 'email' group will only validate constraints with the e-mail group assigned to them
const promise = validator.validate(tags, constraint);
promise.then(function(violations: ConstraintViolationInterface[]) {
if(violations.length > 0) {
// Will contain a violation with the message set to "Element at index 2 is blank"
return console.log(violations);
}
console.log("All tags are valid");
});
Constraints
Out of the box, the following validation constraints are available
NotBlank
Validates that a value is not blank. Meaning not equal to a blank string, false, null or undefined.
Options | Type | Description |
---|---|---|
message | string | The validation message to display when the constraint violation fails. Default to "This value cannot be blank" |
Range
Validates that a value is between a minimum and maximum value
Options | Type | Description |
---|---|---|
min | number | This required option is the “min” value. Validation will fail if the given value is less than this min value. |
max | number | This required option is the “max” value. Validation will fail if the given value is mor than this max value. |
minMessage | string | The message to display if the min validation fails. Defaults to "This value should be %{min} or more." |
maxMessage | string | The message to display if max min validation fails. Defaults to "This value should be %{max} or more." |
Length
Validates that a string length is between a minimum and maximum value
Options | Type | Description |
---|---|---|
min | number | This required option is the “min” value. Validation will fail if the given value's length is less than this min value. |
max | number | This required option is the “max” value. Validation will fail if the given value's length is over this max value. |
minMessage | string | The message to display if the min validation fails. Defaults to "This value should be %{min} characters in length or more." |
maxMessage | string | The message to display if max validation fails. Defaults to "This value should be %{max} characters in length or less." |
Choice
Validates that a value is in a specific choice list
Options | Type | Description |
---|---|---|
choices | array | An array of valid choices. Validation will fail if the given value is not in this array of choices |
message | string | The message to display if the value is not in the given array. Defaults to "This value is not supported." |
Count
Validates that an array has a specific number of elements present
Options | Type | Description |
---|---|---|
min | number | This required option is the “min” value. Validation will fail if the given array's length is less than this min value. |
max | number | This required option is the “max” value. Validation will fail if the given array's length is over this max value. |
minMessage | string | The message to display if the min validation fails. Defaults to "This collection should have %{min} characters in length or more." |
maxMessage | string | The message to display if max validation fails. Defaults to "This collection should have %{max} characters in length or less." |
Regex
Validates that a string matches a given format
Options | Type | Description |
---|---|---|
pattern | RegExp | The pattern to validate against |
match | boolean | Whether the validation constraint should evaluate as true or false. Defaults to true |
message | string | The message to display if the value is not in the correct format. Defaults to "This value is not in a valid format." |
Custom constraints
Although the default constraints are enough in most cases, sometimes you may need to create your own validation and this is achieved using a custom callback constraint
Let's imagine the following scenario where only a Mercedes car is allowed as a value and BMW is disallowed
import { Validator, ConstraintViolationInterface } from "@smayas/validator";
import * as Constraint from "@smayas/validator/dist/constraints";
// callback wil be invoked during validation
const callback = async (value: any, constraint: ConstraintInterface, context: ExecutionContextInterface): Promise < ConstraintViolationInterface[] > => {
const violations = [];
if (value === 'BMW') {
const customViolationErrorCode = 'callback-constraint.invalid-car.error';
const customViolationErrorMessage = 'Only %{allowed_brand} cars are allowed but you provided %{disallowed_brand}';
const customViolationErrorMessageParameters = {
'allowed_brand': 'Mercedes',
'disallowed_brand': value
};
const violation = context.createViolation(constraint, value, value, customViolationErrorCode, customViolationErrorMessage, customViolationErrorMessageParameters);
violations.push(violation);
}
return violations;
};
const validator = new Validator();
const promise = validator.validate('BMW', [
new Constraint.NotBlank({
message: 'A valid car brand must be provided'
}),
new Constraint.Callback({
callback: callback
})
]);
promise.then(function(violations: ConstraintViolationInterface[]) {
console.log(violations);
});
The violatiotion message above will be
Only Mercedes cars are allowed but you provided BMW