Enforcing data validations through readable definitions
enforce is a data validation tool that allows you to assert rules on supplied variables and parameters, using a human-friendly format.
To install enforce, run the following code in your npm project.
npm install --save enforce-jsAfter installing, simply import the module.
import enforce from 'enforce-js';To enforce validation on a variable, simply follow the syntax below.
enforce`${{ variable }} as dataType, rule1, rule2, ...`;// Validate a variable
const message = 'Hello, world!';
enforce`${{ message }} as a string, with 5 to 20 characters`; // okNOTE:
enforceuses double brackets as a shortcut to{ variable: variable }
enforce supports primitive javascript data types, which by default, are non-nullable. To explictly define a variable to be nullable, use the optional keyword.
NOTE: Non-nullable in
enforcemeans the value can either beundefinedor the specified data type. It cannot be a javascriptnullobject.
- 'a string'
- 'a number'
- 'a boolean'
- 'an array'
- 'an object'
- 'a function'
- 'an optional string'
- 'an optional number'
- 'an optional boolean'
- 'an optional array'
- 'an optional object'
- 'an optional function'
- 'a value'
- 'any value'
Additional rules can help further validate a supplied variable. If the below rules do not meet the requirements of what may be needed, you may use the and matches REGEXP rule in order to fill the gap, or you can try Extending Rules.
- 'with
MINtoMAXcharacters' (MIN: number, MAX: number) - 'with
MINor more characters' (MIN: number) - 'with up to
MAXcharacters' (MAX: number) - 'greater than
MIN' (MIN: number) - 'greater than or equal to
MIN' (MIN: number) - 'less than
MAX' (MAX: number) - 'less than or equal to
MAX' (MAX: number) - 'and matches
REGEXP' (REGEXP: regular expression)
enforce also supports validating class-type objects. To validate whether a supplied variable or parameter is an instance of a class, you can directly supply the class as a data type.
class Animal { /* class definition */ }
const dog = new Animal();
enforce`${{ dog }} as an ${{ Animal }}`; // ok
class Dog extends Animal { /* class definition */ }
const corgi = new Dog();
enforce`${{ corgi }} as a ${{ Dog }}`; // ok
enforce`${{ corgi }} as an ${{ Animal }}`; // ok
enforce`${{ dog }} as a ${{ Dog }}`; // error!By default, if a given parameter does not meet the rules provided, a ValidationError will be thrown with a message containing the original definition. To better handle the error, an additional name parameter is also supplied to let you know which parameter was invalid.
const countingNumber = -1;
enforce`${{ countingNumber }} as a number, greater than or equal to 0`;
// OUTPUT
// error.message: 'countingNumber' must be a number, greater than or equal to 0
// error.name: countingNumberThe recommended approach is to have a try-catch block that retrieves the invalid parameter.
import enforce, { ValidationError } from 'enforce-js';
try {
const countingNumber = -1;
enforce`${{ countingNumber }} as a number, greater than or equal to 0`;
}
catch(err) {
if(err instanceof ValidationError) {
console.error(`The error message was: ${err.message}, and the invalid parameter is: ${err.name}`);
}
}NOTE:
enforceformat is also validated and throws aFormatErrorwhen the supplied definition is invalid.
import enforce, { FormatError } from 'enforce-js';
try {
const countingNumber = -1;
enforce`${{ countingNumber }} as a postive number, and is the square root of 4`;
}
catch(err) {
if(err instanceof FormatError) {
console.error(`The error message was: ${err.message}, and the invalid parameter is: ${err.name}`);
}
}If you need additional rules currently not supported by enforce, you can extend the library by using the .extend() method.
enforce.extend(REGEXP, VALIDATOR);
// REGEXP = Regular Expression matching the rule
// VALIDATOR = Function that will check if the supplied value is valid// Extend a new rule
enforce.extend(/^and is equal to \d{1,}$/i, (val, rule) => {
// e.g. rule == 'is equal to 5'
const number = parseInt(rule.slice(rule.lastIndexOf(' ')));
return val === number;
});
// Enforce the new rule
const thisNumber = 5;
enforce`${{ thisNumber }} as a number, and is equal to 5`;// Import module
import enforce, { ValidationError } from 'enforce-js';
// Validate a variable
const message = 'Hello, world!';
enforce`${{ message }} as a string, with 5 to 20 characters`; // ok
// Validate function parameters
const register = ({ username, name, password, age, options }) => {
try {
enforce`${{ username }} as a string`;
enforce`${{ name }} as an optional string`;
enforce`${{ password }} as a string, with 6 to 8 characters`;
enforce`${{ password }} as a password, with 6 to 8 characters, and matches /^\\d{6,8}$/i`;
enforce`${{ age }} as a number, greater than 18`;
enforce`${{ options }} as an optional object`;
const { messages } = options;
enforce`${{ messages }} as a boolean`;
/* function definition */
}
catch(err) {
if(err instanceof ValidationError) {
return `Invalid Parameter: ${err.name}`;
}
}
}
// Use function
const result = register({
username: 'tardisblue', // ok
name: 'Amy Pond', // ok
password: '1234', // error!
age: 21 // ok
});
// result: `Invalid Parameter: password`
// Validate if an object is an instance of a class
class Post { /* class definition */ }
const post = new Post();
enforce`${{ post }} as a ${{ Post }}`; // ok