An options object schema validator for Node.js.
npm install dannynemer/ill-formed-opts
Checks if options
does not adhere to schema
, thereby simulating static function arguments (i.e., type checking and arity). If ill-formed, prints descriptive, helpful errors (including the file-path + line-number of the offending function call).
schema
(Object): The definition of required and optional properties foroptions
.[options]
(Object): The options object to check for conformity toschema
.[ignoreUndefined]
(Object): Specify ignoring non-required
options
properties defined asundefined
. Otherwise, reports them as errors, which is useful for catching broken references.
(boolean): Returns true
if options
is ill-formed, else false
.
var illFormedOpts = require('ill-formed-opts')
var mySchema = {
// Optionally accept an `boolean` for 'silent'.
silent: Boolean,
// Optionally accept an `Array` of `string`s for 'args'.
args: { type: Array, arrayType: String },
// Require `string` 'modulePath'.
modulePath: { type: String, required: true },
// Optionally accept one of predefined values for 'stdio'.
stdio: { values: [ 'pipe', 'ignore', 0, 1, 2 ] },
// Optionally accept an `Object` that adheres to the nested `schema` object.
options: { type: Object, schema: {
cwd: String,
uid: Number,
} },
}
function myFork(options) {
if (illFormedOpts(mySchema, options)) {
// => Prints descriptive, helpful error message
throw new Error('Ill-formed options')
}
// ...stuff...
}
The contents of foo.js
:
myFork({ modulePath: './myModule.js', stdio: 'out' })
Property names and types: mySchema
is an object where each property name defines an accepted options
property. Each mySchema
property value defines the accepted data type(s) for that property using function constructors (e.g., Array
, Object
, Number
, MyClassName
):
var mySchema = {
list: Array,
// => Optionally accepts the `list` property in `options`, which must be an `Array`.
}
When specifying primitive data types (e.g., string
, number
, and boolean
), use their corresponding function constructors even if the passed options
value is instantiated using literals instead of the constructor (and consequently are complex data types):
var mySchema = {
name: String,
// => Accepts primitive type values, `{ name: 'dantil' }`, as well as complex type
// references of the same type, `{ name: String('dantil') }`.
}
Required properties: To require an options
property, set the mySchema
property to an object defining type
and required
:
var mySchema = {
port: { type: Number, required: true },
// => Requires `options` with the property `port`.
}
Variadic types: To accept varying types for an options
property, set the mySchema
property to an object defining type
as an array of function constructors:
var mySchema = {
count: { type: [ Number, String ] },
// => Accepts values for `count` of type `Number` or `String`.
name: { type: [ String ] },
// => Accepts values for `count` of only type `String`.
alias: String,
// => Accepts values for `count` of only type `String` (identical to `name`).
}
Array element types: To accept an Array
containing values of specific type(s), set the mySchema
property to an object defining type
as Array
and arrayType
as the function constructor(s):
var mySchema = {
names: { type: Array, arrayType: String },
// => Accepts an `Array` containing elements of type `String` for `names`; e.g.,
// `{ names: [ 'dantil' ] }`.
paths: { type: Array, arrayType: [ String ] },
// => Behavior identical to `names` property.
values: { type: Array, arrayType: [ Number, String ] },
// => Accepts an `Array` containing elements of type `String` or `Number` for
// `values`.
elements: { type: Array, arrayType: Object, allowEmpty: true },
// => Accepts an `Array` containing elements of type `Object`, and does not report
// an error if the array is empty.
}
Predefined values: To only accept values from a predefined set, set the mySchema
property to an object defining values
as an array of the values:
var mySchema = {
fruit: { values: [ 'apple', 'orange', 'pear' ] },
// => Only accepts 'apple', 'orange', or 'pear' as a value for `fruit`; e.g.,
// `{ fruit: 'apple' }`.
}
Nested object schemas: To recursively check if a passed Object
value adhere to a separate, nested schema, set the mySchema
property to an object defining type
as Object
and schema
as an object following the options
parameterization:
var mySchema = {
childOptions: { type: Object, schema: {
cwd: String,
uid: Number,
} },
// => Recursively checks value for `childOptions` adheres to `schema`.
}