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

sjv

v1.3.0

Published

An easy-to-write schema and deep validator for JSON documents

Downloads

158

Readme

sjv

Build Status

An easy-to-write yet powerful schema validator for objects.

## Features

  • ES5-compatible, uses Promises
  • Elegant, minimal syntax
  • Comprehensive error reporting - all validation failures, not just first one
  • Asynchronous custom validators
  • Type-matching
  • No other library dependencies (small browser footprint)

Installation

This package requires Node 4 or above

$ npm install sjv

To use in the browser ensure you must have a working Promise implementation (e.g. bluebird) available at window.Promise.

Usage

Here is a schema with all the possible field types:

var schema = {
  name: String, // shorthand for `{ type: String }`
  isMarried: Boolean,
  numCars: {
    type: Number
  },
  born: {
    type: Date
  },
  // any plain JS object with any keys
  jobDetails: {
    type: Object
  },
  // a simple array with any data
  favouriteNumbers: {
    type: Array
  },
  // a nested object which adheres to given schema
  address: {
    type: {
      houseNum: {
        type: Number
      },
      // value which must be one of given strings
      taxBand: {
        type: String,
        enum: ['low', 'medium', 'high'],
      },
    },
  },
  // an array of nested objects which must adhere to given schema
  children: {
    type: [{
      name: {
        type: String,
        // custom validators
        validate: [
          function(value) {
            if ('john' === value) {
              return Promise.reject(new Error('cannot be john'));
            } else {
              return Promise.resolve();
            }
          }
        ]
      },
      age: {
        type: Number
      }
    }],
  },
}

Example

First we define the schema:

var EmployeeSchema = {
  name: {
    type: String,
    required: true
  },
  born: {
    type: Date,
  }
  numChildren: {
    type: Number,
  },
  address: {
    type: {
      houseNum: {
        type: Number
      },
      street: {
        type: String
      },
      country: {
        type: String,
        required: true
      },
    },
  },
  spouse: {
    type: {
      name: {
        type: String,
        required: true      
      }
    }
  },
};

var CompanySchema = {
  name: {
    type: String,
    required: true
  },
  employees: {
    type: [EmployeeSchema],
    required: true
  },
};

Now we can validate data against it:

var schema = require('sjv')(CompanySchema);

schema.validate({
  name: 'my company',
  employees: [
    {
      name: 'john',
      born: 'last year',
      numChildren: 1,
      address: {
        houseNum: 12,
        street: 'view road',
        country: 'uk',
      }
    },
    {
      name: 'mark',
      born: new Date(),
      numChildren: null,
      address: {
        houseNum: 25,
        street: 'view road'
      },
      spouse: {
        name: 23,
        age: 23
      }
    },
  ]
})
.catch(function(err) {

  /*
    Error: Validation failed
   */
  console.log(err.toString());  

  /*
  [
    "/employees/0/born: must be of type Date",
    "/employees/1/numChildren: must be a number",
    "/employees/1/address/country: missing value",
    "/employees/1/spouse/name: must be a string"
  ]
  */
  console.log(err.failures);
});

Type matching

When stringifying JSON you often lose type information (e.g. Date instances get converted to strings). When the stringified version gets parsed back into a JSON object you can use the typeify() function to help restore type information:

var schema = {
  name: {
    type: String
  },
  isMarried: {
    type: Boolean
  },
  numCars: {
    type: Number
  },
  born: {
    type: Date
  }
};

var object = {
  name: 'John',
  isMarried: true,
  numCars: 3,
  born: new Date(2015,0,1)
}

var str = JSON.stringify(object);

/*
"{"name":"John","isMarried":true,"numCars":3,"born":"2014-12-31T16:00:00.000Z"}"
*/

var newObject = JSON.parse(str);

/*
{
  name: 'John',
  isMarried: true,
  numCars: 3,
  born: "2014-12-31T16:00:00.000Z"
}
*/

var typedObject = schema.typeify(newObject);

/*
{
  name: 'John',
  isMarried: true,
  numCars: 3,
  born: Date("2014-12-31T16:00:00.000Z")
}
*/

The type-ification process is quite tolerant of values. For example, for boolean values;

  • false <- "false" or "FALSE" or "no" or "NO" or "0" or 0
  • true <- "true" or "TRUE" or "yes" or "YES" or "1" or 1

To take the previous example again:

var newObject = {
  name: 'John'
  isMarried: 'no'
  numCars: '76'
  born: '2014-12-31T16:00:00.000Z'
};

var typedObject = schema.typeify(newObject);

/*
{
  name: 'John',
  isMarried: false,
  numCars: 76,
  born: Date("2014-12-31T16:00:00.000Z")
}
*/

It is also smart enough to know when a conversion isn't possible. Instead of throwing an error it will simply pass through the original value.

Using the schema from our previous example:

var newObject = {
  name: null
  isMarried: function() {}
  numCars: false,
  born: 'blabla'
};

var typedObject = schema.typeify(newObject);

/*
{
  name: null,
  isMarried: function() {}
  numCars: false
  born: 'blabla'
}
*/

You can limit type-ification to certain types only by setting the limitTypes option:

var newObject = {
  name: 23,
  isMarried: '0',
  numCars: '3',
  born: '2018-01-01'
};

var typedObject = schema.typeify(newObject, { limitTypes: [String]});

/*
{
  name: '23',
  isMarried: '0',
  numCars: '3',
  born: '2018-01-01'
}
*/

Building

To run the tests:

$ npm install -g gulp
$ npm install
$ npm test

Contributing

Contributions are welcome! Please see CONTRIBUTING.md.

License

MIT - see LICENSE.md