Tuesday, August 30, 2016

Schema Check

It has been a while since I've done a post about side projects, but lately I've been working on a little NPM Module called Schema Check, available on NPM and Github and wanted to share it.  Schema Check is a light JavaScript object type enforcer which uses private properties and Object.defineProperty to create getters and setters for various fields on a JavaScript object.

Schema Check uses schema objects to describe the fields on the object and the types they should accept.  It then modifies the getters and setters of that object to only allow values of that type to be set.  This came out of a desire to have something that could be used to enforce some types in JS without resorting to something like TypeScript entirely.  It's also just a fun side project I can work on here and there in my spare time.

How it works

Schema Check at it's core is built on Object.defineProperty.  By using defineProperty, schema check allows you to apply a schema to an existing object - which will force the fields of that object to conform to certain restraints.

Take for example, the following object:

  var dude = {
    name: "Chad",
    is_single: true,
    cash: 100  

Our dude, Chad, has three properties: name (a string), is_single (a boolean) and cash (a number).  If we're manipulating data and working with the dude object in JavaScript, it'd be really nice to limit what we can set to those fields.  There are many solutions for this, such as the rise of TypeScript, but Schema Check is a lightweight way to enforce these values with a simple schema.

By importing schema check like so and setting a schema for the dude object, we can force the object to throw an error (or fail silently) when an invalid value is set to that property.

  var SchemaCheck = require('schema-check');

  var schema = {
    name: {
      type: 'string',
      regex: /^[a-z]+$/i  //Used by Regex.test() to check validity
    is_single: {
      type: 'boolean',
      is_editable: false //Poor chad - this status isn't changing any time soon
    cash: {
      type: 'number',
      allow_nulls: false //This can be true too if you want to 
                         //allow null to be a valid entry

  var options = {
    throw_error: false 
      //This will determine whether or not trying to set 
      //an invalid property type throws an error or fails silently

  SchemaCheck(dude, schema, options);

  dude.name = 5;           //Fails - name is still Chad
  dude.name = '123';       //Also Fails - because it doesn't match the regex.test
  dude.is_single = false;  //Fails - Chad is still single
  dude.cash = 110;         //Succeeds, Chad is a bit richer now!

I have a lot more I want to do with the library.  At the moment it doesn't really support Arrays and there are extra restrictions I want to add as well (like Min/Max for numbers)

It's a work in progress, feel free to contribute to the GitHub repo and create PRs and Issues if you think of anything that should be added.