npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

tiny-object-validator

v1.0.5

Published

Small library to organise JavaScript/TypeScript objects' validation

Downloads

6

Readme

Tiny Object Validator

Tests

A small library to handle validation of an object's properties using field rules.

'Tiny' because it only concern itself with providing a mechanism to inspect and object and applying user defined rules rather than duplicating the effort of well established validation libraries such as validator.js.

Typically used in conjunction with the latter to do the actual data validation.

Why I built this library

In a nutshell, I needed a pure JavaScript approach to data validation in Vue3, not relying on any logic held in view components or clunky HTML5 data validation.

Installation

yarn add tiny-object-validator

or

npm i --save tiny-object-validator

Getting Started

Let's say we have a model object populated by our UI for user registration:

const model = {
    email : 'test@example',
    password : '123456',
    acceptConditions : false
}

The validation result will be stored in a ValidationState object that we'll need to pass to validate.

const stateObj: ValidationState = {
    isValid : false,
    fields : {}
}

The false value for each field is the validation initial state which means that the field hasn't been validated (yet).

Then, we define the rules:

const fields : ValidationFields = [
    {
        name : 'email',
        emptyFieldMessage : 'Your email address is required'
        tests : [
            {
                fn : isEmail //using validator.js' on isEmail function
                message : ({source}) =>  `${source.email} doesn't seem to be a valid email`
            }
        ]
    }, {
        name : 'password',
        tests : [
            {
                fn : value =>  !['123456', 'password'].includes(value),
                message : 'Seriously?!?'
            }, {
                fn : value => value.length >= 8,
                message : 'The password needs to be at least 8 characters long'
            }
        ],
        stopOnFailure : 'tests'// the first test to fail will stop tests evaluation and set the field's failure message
    }, {
        name : 'acceptConditions',
        tests : [
            {
                fn : value => !!value,
                message : 'Please accept term and conditions'
            }
        ]
    }
]

Finally, we can validate our data. The ObjectValidator only needs to be instanciated once. Our app will call the validate method whenever appropriate, either on form input or form submit.

const validator = new ObjectValidator(fields);

const valid = await validator.validate({source : model, stateObj});

stateObj will be mutated atomically at the end of the validation and it will look like this:

{
    isValid : false,
    fields : {
        email : '"test@example" doesn\'t seem to be a valid email',
        password : 'Are you serious?!?',
        acceptConditions : true
    }
}

stateObj : ValidationState

This object, passed to validate, gets populated with the validation result.

isValid will be set to true if validation succedes fields will be filled with all the source data object properties paths to be validated

The value for each fields entry will be:

  • false if the field wasn't validated
  • true if the field passed validation
  • a string with the validation failure description

Deep fields can be declared using dot notation, such as address.postal_code

Note for Vue3 developers

If we're relying on Vue3 reactivity for the UI to see stateObj to give feedback to the client, the fields property must be populated like this:

const stateObj: ValidationState = {
    isValid : false,
    fields : {
        email : false,
        password : false,
        acceptConditions : true
    }
}

The context object

An optional object/array can be passed to validate to provide additional data/functions to the validation process.

A context object (ValidationContext) will be passed to:

  • tests' fn and message when the latter is a function
  • fields' skipIf
  • fields' emptyFieldMessage when it's a function

This could be used to provide additional information/functionality when processing validation.

For instance, it can be used when a field depends on other field's value for validation.

const data = {
    locale : 'US',
    postal_code : '12345'
}

const fields = [
    {
        name : 'locale',
        tests : [
            {
                fn : value => ['US', 'AU', 'UK', 'CA'].includes(value)
                emptyFieldMessage : 'Please select a country'
            }
        ]
    }, {
        name : 'postal_code',
        skipIf : ({source}) => !source.locale,
        tests : [
            {
                fn : (value, {source}) => isPostalCode(value, source.locale),
                message : `This doesn't seem like a postal code for the selected country`
            }
        ]
    }
]


validator.validate({
    source : myData,
    stateObj
});

Interrupting validation

It's possible to prematurely interrupt validation at two levels:

  • tests the currently evaluated array of tests for a field will stop and the latest validation result for the field will be used
  • fields the whole validation will terminate after setting the current field's validation result.

This is handled at field's level using stopOnSuccess (which makes tests behave in a or fashion) or stopOnFailure (which makes tests behave in a and fashion).


const fields = [
    {
        name : 'ip_address',
        tests : [
            {
                fn : isIP4
            }, {
                fn : isIP6,
                message : 'Please enter either a IPv4 or a IPv6 address'
            }
        ],
        stopOnSuccess : 'tests'
    }
]