Use this module to validate input or configuration parameters provided
as JSON. You can ensure that the JSON structure and data types are
what you need. You'll get friendly, useful error messages for your
users, and that makes your API better!

var parambulator =require('parambulator')

var paramcheck = parambulator({

price:{type$:'number'}

})

// this passes

paramcheck.validate({ price:10.99},function(err){console.log(err)})

// this fails - price should be a number

paramcheck.validate({ price:'free!'},function(err){console.log(err)})

// output: The value 'free!' is not of type 'number' (parent: price).

Why?

You're writing a module and you accept configuration as a structured
JavaScript object. For example, opening a database connection:
MongoDB driver. Or
you want to have named parameters:
http.request.

It's nice to be able to validate the input and provide useful error messages, without hand-coding the validation.

But What About JSONSchema!

Yes, JSONSchema would be the proper way to do this. But the syntax is too hard, and the error messages aren't friendly. This is a Worse is Better! approach.

There's also a philosophical difference. JSONSchema defines a formal structure, so you need to be fairly precise and complete. Parambulator defines a list of rules that are tested in the order you specify, and you can be vague and incomplete.

This is a function that creates Parambulator object instances. This function accepts two arguments:

spec - the rule specification to test against

pref - your preferences, such as custom error messages and rules

Example:

var paramcheck = parambulator({ price:{type$:'number'}})

The paramcheck variable is an instance of Parambulator. This object only has one method: validate, which accepts two arguments:

args: the object to validate

cb: a callback function, following the standard Node.js error convention (first arg is an Error)

Example:

paramcheck.validate({ price:10.99},function(err){console.log(err)})

The callback function is called when the validation has completed. Processing of rules stops as soon as a rule fails. If validation fails, the first argument to the callback will be a standard JavaScript Error object, with an error message in the message property.

The validation rules are defined in the spec argument to parambulator. The rules are specified as an object, the properties of which are the rule names, and the values the rule options, like so: {required$:['foo','bar']}. The rules are executed in the order that they appear (JavaScript preserves the order of object properties).

Rule names always end with a $ character. Properties that do not end with $ are considered to be literal property names:

{

required$:['foo','bar'],

foo:{

type$:'string'

}

}

This specification requires the input object to have two properties, foo and bar, and for the foo property to have a string value. For example, this is valid:

{ foo:'hello', bar:1}

But these are not:

{ foo:1, bar:1}// foo is not a string

{ foo:'hello'}// bar is missing

The rules are evaluated in the order they appear:

at the current property (i.e. the top level), check for properties foo and bar, as per required$: ['foo','bar']

descend into the foo property, and check that it's value is of type$: 'string'

You can nest rules within other rules. They will be evaluated in the order they appear, depth first.

For each input property, the rules apply to the value or values within that property. This means that your rule specification mirrors the structure of the input object.

For example, the specification:

{

foo:{

bar:{ type$:'integer'}

}

}

matches

{ foo:{ bar:1}}

but does not match

{ bar:{ foo:1}}

In general, rules are permissive, in that they only apply if a given property is present. You need to use the required$ rule to require that a property is always present in the input.

Each rule has a specific set of options relevant to that rule. For example, the required$ rule takes an array of property names. The type$ rule takes a string indicating the expected type: string, number, boolean, etc. For full details, see the rule descriptions below.

Literal properties can also accept a wildcard string expression. For example:

Each rule has an associated error message. By default these explain the reason why a rule failed, and give the property path (in standard JavaScript dot syntax: foo.bar.baz) of the offending value. You can customize these error messages, by providing your own string templates, or by providing a function that returns the error message text.

Use the msgs property of the pref argument (the second argument to parambulator) to define custom error messages:

var pm = parambulator({...},{

msgs:{

required$:'Property <%=property%> is required, yo!'

}

})

The template syntax is provided by the underscore module: http://underscorejs.org/#template

The following properties are available:

property: the relevant property name

value: the string representation of the value that failed in some way

point: the actual value, which could be of any type, not just a string

Specify a set of required properties. Accepts an array of property name strings, or a single property name. Wildcards can be used. All properties must be present in the current point. Can also appear as a rule specification for literal properties.

Specify a set of properties that cannot be empty, if they are present. Unlike required$, these properties can be absent altogether, so use required$ if they are also required! Accepts an array of property name strings, or a single property name. Wildcards can be used. All properties are relative to the current point. Can also appear as a rule specification for literal properties.

Specify a regular expression that the property value must match. The property value is converted to a string. The regular epxression is given as-is, or can be in the format /.../X, where X is a modifier such as i.

You can write your own rules if you need additional validation. The range.js example shows you how.

Define your own rules inside the rules property of the prefs argument to paramabulator. Each rule is just a function, for example:

var pm = parambulator({...},{

rules:{

mynewrule$: function(ctxt,cb){

...

}

}

})

Dont forget the $ suffix!

The ctxt parameter provides the same interface as the inserts object for custom messages (as above). You can execute callback or evented code inside the rule function. Call the cb callback without any arguments if the rule passes.

If the rule fails, you can use a utility function to generate an error message:

By the way, if you have a cool new rule and you thing it should be built-in, send me a pull request! Just follow the pattern for, say, wild$ in parambulator.js. You'll need entries in rulemap, msgsmap, and ownparams.

There is a gotcha. You need to escape the rule names, so that they are treated as literal properties, and not rules. To do this, use the prop$ pseudo-rule:

{ prop$:{name:'foo', rules:{type$:'string'}}}

is equivalent to:

{ foo:{type$:'string'}}

The other pseudo-rule that may come in handy is the list$ rule. This lets you specify rules using an array. Each element is a sub array with two elements, the first is the rule name, and the second the rule specification

{

list$:[

['foo',{type$:'string'}],

['bar',{type$:'string'}],

]

}

Take a look at the definition of ownparams in parambulator.js to see how parambulator validates its own input.