object-validator-pro

More than just an object validator.


Project maintained by trapcodeio Hosted on GitHub Pages — Theme by mattgraham

< Basics


How to create a Validator

Creating powerful validators is very easy with OVP.

// having initialized OVP
ovp.addValidator(name, validationFn, error);
Argument Description
name Name of the validator e.g: min or max etc…
validationFn Function to handle validation.
error Error Message.

The error message can parse two keywords if found.

:param: The key of the object being validated.

:option: The option passed to the validator in the rules object.

Your validationFn must return true or false and receives 3 arguments on validation. e.g

Argument Description
val Value of the key in the object being validated.
opt Option passed in the rule.
obj An ObjectOnValidation class to modify the current object being validated
// First we create a validator named: MyValidator
ovp.addValidator('myValidator', (...args) => {
    console.log(args);
    return false;
}, ':param failed myValidator');

The above syntax creates a validator named myValidator and logs all the arguments it receives. Now lets run some validation to see how this turns out.

// An object to validate
let ourObject = {
    hobbies: ['eat', 'code', 'sleep'],
    website: {
        name: 'My Website',
        url: 'some-blog-in-3030.com'
    }
};

// Rules to validate with
let rule = {
    hobbies: {myValidator: 'any'}
};


// Run Validation
let isValid = ovp.validate(ourObject, rule);
console.log(isValid);
// logs
[[ 'eat', 'code', 'sleep' ], 'any', ObjectOnValidation]
[ 'hobbies', 'Hobbies failed myValidator' ]
false

The log above explains that val argument in validationFn is the value of the key in the object we are validating i.e ourObject.hobbies.

opt is the value passed to myValidator rule i.e ‘any’, while obj is a helper class to modify the object we are validating.

Lets a create validator that checks if ourObject.hobbies has an item “drink” and another validator that checks if ourObject.website.url has “http://”

ovp.addValidator('NoDrinkInHobbies', (hobbies) => {
    if(hobbies.indexOf('drink') >= 0) {
        return false;
    }
}, 'Drink found in :param');

ovp.addValidator('hasHttp', (url) => {
    if(url.substr(0, 7) !== 'http://'){
        return false;
    }
}, ':param must start with http://');


// new rule
let rule = {
    hobbies: {NoDrinkInHobbies: true},
    'website.url': {hasHttp: true}
};

// Run Validation
isValid = ovp.validate(ourObject, rule);
console.log(isValid);

// Assuming...
ourObject.hobbies = ['eat', 'code', 'sleep', 'drink'];

// Rerun Validation
isValid = ovp.validate(ourObject, rule);
console.log(isValid);
// Before Assumption
[ 'website.url', 'Website Url must start with http://' ]
false

// After Assumption
[ 'hobbies', 'Drink found in Hobbies' ]
false

In the first validation, website.url fails because hasHttp validator returned false. After changing the value of ourObject.hobbies the second validation fails because NoDrinkInHobbies returned false.

Sometimes not all validations requires program halt, some validations are for fixing things.

e.g Instead of stopping the above process because website.url does not have “http://”, why don’t we add it ourselves?

// lets add a different validator
ovp.addValidator('addProtocol', (url, protocol, obj) => {
    protocol = protocol + '://';
    if (url.substr(0, protocol.length) !== protocol){
        obj.setThis(protocol + url);
    }
});

ovp.validate(ourObject, {
    'website.url': { addProtocol: 'ftp' }
});
console.log(ourObject.website.url);
// logs: ftp://some-blog-in-3030.com

// Rerun with http instead
ovp.validate(ourObject, {
    'website.url': { addProtocol: 'http' }
});
console.log(ourObject.website.url);
// logs: http://some-blog-in-3030.com

Notice our new validator does not have an error? this is because we know this has no errors.

obj.setThis? this is a function in the ObjectOnValidation Class. .setThis sets the value of the current key we are validating. i.e

// this line
obj.setThis(protocol + url);

// is equivalent to
ourObject.website.url = protocol+url;

// can also be set like this
obj.set('website.url', protocol+url);

// any key of the obj can be modified or created using
obj.set(path, value);

Do see the ObjectOnValidation Class. It provides great helpers that assists with current object on validation modification.

Async Validators

Ovp handles async validators using the validateAsync function.

validatorFn must also have async before it to be treated as async. All async validators are waited for and a Promise<boolean> is returned to you.

Lets check if website.url is a valid url using axios.

const axios = require('axios');

// lets add urlIsOnline Async validator.
ovp.addValidator('urlIsOnline', async (value) => {
    try{
        await axios.get(value);
        return true;
    }catch(e){
        return false;
    }
}, 'Url is not online!');

let asyncTestData: {
  url: 'some-blog-in-3030.com'  
};

let asyncRule = {
    'url': {addProtocol: 'https', 'urlIsOnline': true}
};

ovp.validateAsync(asyncTestData, asyncRule).then((isValid) => {
    // isValid is false;
});

// if you are in an async function you can use await instead
let isValid = await ovp.validateAsync(asyncTestData, asyncRule);
// isValid is false;

UrlIsOnline returned false because at the time of this documentation https://some-blog-in-3030.com is not online.

You should change the url to “google.com” and urlIsOnline will return true.

Adding Bulk Validators

You can set more than one custom validator using the ovp.addBulk(arrayOfValidators)

ovp.makeValidator(): returns the object data of a validator, works just like the new Validator function but returns the validators data instead of setting them.

See example below to see how it works.

// Using ovp.makeValidator method
let emailValidator = ovp.makeValidator('isEmail', (email) => {
    return (typeof email === "string" && email.length>5 && email.includes('@'));
}, ':param does not look like an email');

let arrayOfValidators = [
    // Using Object Method
    {
        name: 'exact',
        error: ':param is not what we are expecting!',
        validator: (value, option) => {
            return value === option;
        }
    },

    // Using Object Method
    {
        name: 'strongPassword',
        error: ':param is not strong. no Capital letter found!',
        validator: (value) => {
            return value.toLowerCase() !== value;
        }
    },

    // Using ovp.makeValidator method Object from above
    emailValidator,
];

console.log(arrayOfValidators);

/*
returns: =====>
[ { name: 'exact',
    error: ':param is not what we are expecting!',
    validator: [Function: validator] },
  { name: 'strongPassword',
    error: ':param is not strong. no Capital letter found!',
    validator: [Function: validator] },
  { name: 'isEmail',
    error: ':param does not look like an email',
    validator: [Function] } ]
*/


ovp.addBulk(arrayOfValidators);

The data return by emailValidator in the console results is the same with the Objects manually declared in arrayOfValidators So you can populate arrayOfValidators any which way you find preferable.

Modifying Validators

Lets say for some reason you want to overwrite a validator that has been defined somewhere or somehow.

You can simply create a new validator with new validator function and error but same name. like below.

// Old validator.
ovp.addValidator('checkName', () => {
    return true;
}, '1st Error message.');

// Overwrite using this.
ovp.addValidator('checkName', () => {
    return false;
}, 'Overwritten Error message.');

The above will work perfectly but OVP also includes an easy method to modify validators.

using ovp.addValidator(name) with only name as argument enables modification or creation using .save()

// Modify only validationFn
ovp.addValidator('checkName').validator(() => {
    return true;
}).save();

// Modify only error
ovp.addValidator('checkName').error('New Error Message.').save();

You can use any style you feel comfortable with.