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

vuex-store-validator

v2.0.7

Published

Validate Vuex Commits with Joi, Superstruct & Yup Schema

Downloads

13

Readme

:gift: Vuex Store Validator

Vuex Store Validator

Build Coveralls npm npm

This package helps you to validate how you mutate your Vuex store. You can say that it is a Validator for the mutations. You can easily validate the payload for each of your mutations, so that you can be sure of the integrity of your Store Data.

This package also has support for any custom schema validator you may choose. You can create your own implementation and extend this package to use that schema.

Though Vuex allows you to set the store state directly without calling any mutation. This package won't validate anything outside the mutations.

:package: Installation

// NPM:
$ npm install --save vuex-store-validator

// Yarn:
$ yarn add vuex-store-validator

By default it comes with Joi validator. It also has support for Superstruct and Yup validation engine. Read their respective docs to find out which one is best for you.

It did come with Ajv validation engine on ^1.0 but for the sake of bundle size it is removed from the bundle, but no need to worry, you can still make use of it by providing custom validator to the package.

Setup Joi

If you want to use joi then you'll have to install it as your project dependency.

// NPM:
$ npm install --save joi

// Yarn:
$ yarn add joi

Setup Superstruct

If you want to use superstruct then you'll have to install it as your project dependency.

// NPM:
$ npm install --save superstruct

// Yarn:
$ yarn add superstruct

Setup Yup

If you want to use yup then you'll have to install it as your project dependency.

// NPM:
$ npm install --save yup

// Yarn:
$ yarn add yup

Setup Ajv

If you want to use ajv then you'll have to install it as your project dependency.

// NPM:
$ npm install --save ajv

// Yarn:
$ yarn add ajv

After that, see how to setup AJV with this package here: Custom Validator Usage

:fire: Usage

  1. Add the validator to the plugins section of your Root Store.
// store.js
import VuexStoreValidator from 'vuex-store-validator';

export default new Vuex.Store({
    ...
    plugins: [new VuexStoreValidator()],
});
  1. Add Rules to your store and respective modules
// store.js
import VuexStoreValidator, { ENGINE } from 'vuex-store-validator';

export default new Vuex.Store({
    rules: {
        SET_USER: ...SCHEMA HERE...
    },
    state: {user: null},
    mutations: {
        SET_USER(state, user) {
            state.user = user;
        }
    },
    plugins: [new VuexStoreValidator()],
});

// Joi Schema...
import Joi from 'joi';
SET_USER: Joi.object({
    name: Joi.string().required(),
    age: Joi.number().required(),
}).required(),

// Superstruct Schema...
import {object, string, number} from 'superstruct';
SET_USER: object({
    name: string(),
    age: number(),
}),

// Yup Schema...
import {object, string, number} from 'yup';
SET_USER: object().shape({
    name: string().required(),
    age: number().required(),
}).required(),

NOTE: If you want to use anything other than Joi then, you will have to add the engine option in the plugin registration

// Superstruct...
plugins: [new VuexStoreValidator({engine: ENGINE.SUPERSTRUCT})],

// Yup...
plugins: [new VuexStoreValidator({engine: ENGINE.YUP})],

:tada: Congratulations! You're all done.

Now whenever you call the mutation from anywhere be it inside an action or from any component. The payload you pass will be validated against the schema you've defined.

For the above piece of code if you try and call the SET_USER mutation without valid data:

// From a Component
this.$store.commit('SET_USER', {name: 'John'});
// Or from an action
login({commit}, user) {
    commit('SET_USER', {name: 'John'});
}

// Result: 
// ValidationError: "email" field is required for mutation: SET_USER

This will work for all the nested modules as well. Just remember to add a new rules option to your module definition with state, action etc.

:star: Closure Support

Let's face it, the real world projects are complex. It's not as straight forward as defining a schema. Sometimes you need to have conditional schema which depends on some other state property or the mutation payload itself.

But don't worry, you can even define the schema in a closure. You have 2 parameters available in that closure. The store and the mutation payload itself.

Example:

rules: {
    SET_USER(store, data) {
        // Store -> Global Store instance
        // Data -> {name: 'John'}

        return Joi.object({
            ...
        });
    }
}

:muscle: Strict Mode

What if you don't specify any schema for your Legacy Store?

That's not a problem at all. Your project will work as is. This package will only validate the ones for which you have specified a schema. Unless you are using this package in Strict Mode.

// store.js
import VuexStoreValidator from 'vuex-store-validator';

export default new Vuex.Store({
    ...
    plugins: [new VuexStoreValidator({strict: true})],
});

If you set strict mode to true, then if you don't have a schema defined for any of your mutation, it will throw an exception.

:boom: Custom Validator Usage

import Ajv from 'ajv';

// Define an async validator...
/**
 * It accepts the schema and the data payload
 * It should throw an error if your validation fails OR
 * The return value should be the error string or null
 */
const ajvEngine = async (schema, data) => {
  const ajv = new Ajv({ jsonPointers: true, $data: true });
  const validate = ajv.compile(schema || {});

  await validate(data);
  if (validate.errors) {
    throw new Error(validate.errors.map((item) => item.message).join(', '));
  }
};

// Now extend with the custom validator...
plugins: [
    new VuexStoreValidator({
        engine: 'ajv',
        extend: {
            ajv: ajvEngine,
        },
    })
]

// Make sure that the engine name and the extend key are the same

// Now your schema would look something like this:
rules: {
    MUTATION_NAME: {
        type: 'object',
        properties: {
            name: {
                type: 'string',
            },
            age: {
                type: 'number',
            },
        },
        required: ['name', 'age'],
    },
}

You can also leverage Vue PropType Validator and make your own implementation of that. Maybe even React PropType validator. Or anything you like.

:eyes: Caution

This package won't prevent you from setting invalid data to your store. But it will throw appropriate exception every time you set invalid data, so that you can be aware of where bad data might be coming from.

You can see and debug your code based on the Production Logs related to any bad data. If you are using Ignition or Sentry.

:microscope: Testing

After Cloning the repository, install all npm dependencies by running: npm install.

Then Run Tests:

$ npm run test

:date: Change log

Please see CHANGELOG for more information on what has changed recently.

:heart: Contributing

Please feel free to contribute ideas and PRs are most welcome.

:crown: Credits

:policeman: License

The MIT License (MIT). Please see License File for more information.