0.2.1 • Published 8 years ago

xcheck v0.2.1

Weekly downloads
3
License
MIT
Repository
github
Last release
8 years ago

node-xcheck

Build Status Coverage Status

Templated data validation for Node.js.

What' xcheck For?

Suppose that you are implementing several service APIs. Each API accepts an object as argument and returns something. Your code probably goes like this:

function myService(query){
  // validates the arguments
  let name = query.name || 'anonymous';
  let secret = query.secret || '';
  let email = query.email;
  if (!email){
    throw new Error('email is required.');
  }

  // work, work, work

  return data;
}

This is no big deal, though the argument validation is a bit tedious. But when things get more complicated, you have to write dozens of if-else to do the validation. That's quite awful and error prone.

xcheck will do the dirty work for you.

Quick Start

To install xcheck:

npm install xcheck

Simple usage:

const xcheck = require('xcheck');

let template = xcheck.createTemplate({
  name: 'anonymous',
  secret: '',
  'email required': ':string'
});

// d1 will fail the validation
let d1 = {name: 'tom', secret: '******'};
template.validate(d1); // will throw TypeError

// d2 will pass the validation
let d2 = {email: 'hi@example.com'};
template.validate(d2, {applyDefaults: true});

console.log(d2.name);   // 'anonymous'
console.log(d2.secret); // ''
console.log(d2.email);  // 'hi@example.com'

Now, some explanation for how xcheck works.

By calling xcheck.createTemplate({...}), an ObjectTemplate is created, which defines a couple of constraints on an object as below:

  • The object should be of Object type, not a string, a number or anything else.
  • The object may have 2 properties:
    • name, which should be a string. If name is missing in the object, name has a default value "anonymous".
    • secret, which should be a string and, if missing, is defaulted to empty string.
  • The object should have email property, which should be a string.

Then by calling template.validate(d1), d1 is validated for compliance with these constraints. Since email property is required by the template but d1.email is undefined, d1 will fail the validation. Thus a TypeError exception will be thrown.

With applyDefaults option is set true, template.validate(d2) will add any properties that are missing into the validated object. Thus d2.name is assigned default value 'anonymous'.

Template Syntax

Actually, xcheck can also validate Array, string, number and etc. Besides ObjectTemplate, there are ArrayTemplate and ValueTemplate. Templates can be nested composed exactly as JSON.

ValueTemplate :=     "typename SP [default SP json_value]" | ObjectTemplate | ArrayTemplate

ArrayTemplate :=     [ ValueTemplate ]

ObjectTemplate :=     { PropertyTemplate [,PropertyTemplate] }

PropertyTemplate :=     " property_name [required] [nullable] [default SP json_value]" : ValueTemplate

Here are supported built-in typename's:

typenameNode.js typesince
:numbernumber*
:intnumber, accepts only integer*
:stringstring*
:charstring, accepts single character*
:booleanboolean*
:nullobject, accepts only null*
:any*0.2.0

Note that typename is prefixed with a colon. So if you want to create a string template that has a default value starts with colon, you need to add an extra colon. let str = xcheck.createTemplate('::my string starts with colon');

Here are more examples to build templates:

// creates a ValueTemplate that accepts an int
let int = xcheck.createTemplate(":int default 1");

// atomic value template with default value can be shortened
int = xcheck.createTemplate(1); // exactly same as above
let str = xcheck.createTemplate(''); // accepts string, defaults to empty string

// creates an ArrayTemplate that accepts Array<String>
let strarray = xcheck.createTemplate(['']);
strarray.validate(['this', 'is', 'ok']); // ok
strarray.validate([1, 2, 3]); // fail
strarray.validate(['this', 'is', 'weird', 1, 2, 3]); // fail

// creates an ObjectTemplate that accepts complex objects
let t = xcheck.createTemplate({
  'names required': [':string'],
  'courses required': [{
     'id required': ':int',
     'code required': ':string',
     'level': 1
  }],

  // location should be Array<String>, defaults to ['CN']
  'locations default ["CN"]': [":string"]
});

Generally you do not care about what type of the template is. Just describe what you want, call xcheck.createTemplate(), then validate data using the returned template.

Restrictions

These are what xcheck can't do for you:

  • Validating an array of isomers.
  • Tricky validation, i.e. you should check the correctness of a URL by yourself.

Comming More Features

The following features are in plan:

  • Supports for code snippet in ValueTemplate: :int {value>=0} or :string {value.length <= 5}.