bulk-validator
Data validator which allows:
- defining customizable validators (global and local)
- defining aliases (global and local)
- validate data in bulk operation
- canonization of data
- retrieve list of errors
- retrieve list of valid values
- allow optional data and default values
- perform strict/non-strict validation
Contents
- Installation
- Basic Usage
- Validator global options
- Notes about transformation functions
- List of default validators
- List of default aliases
- Defining aliases
- Defining custom validators
- Defining and using schemas
- Running tests
Installation
Install with npm
npm install bulk-validator
Basic Usage
var Validator = Validator;var weekDays = MON: 0 TUE: 1 WED: 2 THU: 3 FRI: 4 SAT: 5 SUN: 6 ; // perform data validation of some common data in a bulk operationvar validator = ; validator ; // check for errorsifvalidator return status: 'error' errors: validator ; // get the valid datavar validData = validator;/* // note how luckyNumber and male have been converted to Number and Boolean // day also has been returned as its enumerated value instead of the key { "name": "Daniel Berlanga", "luckyNumber": 7, "birthday": "1801-04-09", "male": true, "day": 4 }*/
Validator global options
This is the list of global options of the validators.
They can be accessed and modified through the static object in Validator.defaultOptions
,
which will be applied to all the new instances created.
Instances created before modifying this object won't be affected.
ValidatordefaultOptionsoptional = false;var v1 = ;ValidatordefaultOptionsoptional = true;var v2 = ;// v1 still has optional set to false// v2 has optional set to true by default
This options can be overridden in each validation like this:
var v = defaultValue: -1 returnNullOnErrors: false; v ; v; // { n1: 0, n3: -1, n4: 100 }v; // { n2: undefined }
strict
If set to true
, default validators will usually apply strict comparison/validation
(i.e. using ===
instead of ==
, or doing type checking).
It's also one of the options passed to the custom validators, and can/need be used when implementing them.
Default value: false
canonize
When true
, if the data is valid, it's value will be converted to the one returned by the
validator. If false
, the data will be validated but the original will be preserved
(i.e. v.num('n', '123')
will return 123
or '123'
depending on this option)
Default value: true
returnNullOnErrors
If this option is true
and any of the passed data fails the validation, calling valid()
will return null
. Set to false
if you still want to retrieve the valid values.
Default value: true
stopAfterFirstError
If you don't care about providing (a lot of) information of the failed validation, you
can set this option to true
and no other validation will be performed once there's an error.
This should give you a few more free CPU cycles ;)
Default value: false
optional
Mark the data as optional (all of them is specified in Validator.defaultOptions
, the
options passed to the Validator constructor, or only a parameter if passed to a validation
method.
If true
, a validation won't fail if the data value is undefined
and the data
will be asigned with defaultValue
if specified.
It will still fail for other values like null
, 0
, false
, etc.
Default value: false
defaultValue
If options.optional
is set to true
and the data is undefined
, it will be assigned
with the value defined here.
Example:
v = ;v; // v.valid().data === 'hello world'
Default value: undefined
returnUndefined
If a value is validated with undefined
, and this option is false
, it won't be included in the list of valid values.
This is useful when we want define a schema with optional values, and we set options.optional
to true
.
Default value: true
validators
List of validators to add locally to a new Validator when instanciated.
It should be defined as set like { name: definition }
Example:
var v = validators: { return data: data valid: true ; }; v;v;v;
Default value: undefined
allowOverwriteValidator
This option protects the already created validators.
Set it to true
if you wanna get rid of any of them or override its behavior with a custom one.
Note:
Trying to override any method with this option set to false
will throw an Error
.
Default value: false
includeExternal
This option allows to return the data (in valid()
or errors()
depending on externalShouldFail
option) instead of ignoring the data without a definition when validating objects in an schema.
Example
var v = ;v;var data = foo: 123 bar: 'xyz' other: 'external'; v;// v.valid() === { foo: 123, bar: 'xyz' }// v.error() === null v;// v.valid() === { foo: 123, bar: 'xyz' }// v.error() === { other: 'external' } v;// v.valid() === { foo: 123, bar: 'xyz', other: 'external' }// v.error() === null
Default value: false
externalShouldFail
This option is only used when includeExternal
is true
(otherwise external values are just ignored).
By default, external values will fail the validation as they are not defined in the schema, but setting this option to false
will return them in the valid()
result:
var v = ;v;var data = foo: 123 bar: 'xyz' other: 'external'; v;// v.valid() === { foo: 123, bar: 'xyz' }// v.error() === { other: 'external' } v;// v.valid() === { foo: 123, bar: 'xyz', other: 'external' }// v.error() === null
Default value: true
preTransform
Setting this option to a function, you can set it to be called everytime a validation is going to be done, before it happens. The input data is the raw value to be validated, and the result is the actual value that is going to be passed to the validator.
Example
// get the data and return it times 10 { return data * 10;} // validate only numbers greater or equal than 50var v = ;// 10 without transform is 10v;// 10 transformed, is 100v; // v.valid().transformed === 100// v.errors().raw === 10
Applying it to the raw data means that if the data to validate is an array or an object, it's applied to the whole data itself, not to each of its elements.
{ if return data; else if return extra: 0 ...data ; else return data; } var v = preTransform: addElement ;v;v;v; // v.valid() === {// single: 123,// list: [10, 20, 30, 0],// object: { a: 10, b: 20, c: 30, extra: 0 },// }
If the transformation data triggers any error, the data won't validate.
Default value: undefined
preTransformItem
Works like preTransform
but the callback is applied to each element before the validation (but after preTransform
is applied):
// validate only numbers greater or equal than 50var v = min: 50 ; v;v;v;v;v;v; // v.valid() === {// transformedSingle: 100,// transformedList: [100, 200, 300],// transformedObject: { a: 100, b: 200, c: 300 },// } // v.errors() === {// single: 10,// list: [10, 20, 30],// object: { a: 10, b: 20, c: 30 },// }
postTransformItem
Works like preTransformItem
but the callback is applied to each item, after the validation.
postTransform
Works like preTransform
but the callback is applied just before the data is returned (and after all preTransformItem
are applied).
Notes about transformation functions
When applying transformations, the process is like described here:
- Apply
preTransform
functions (if defined) to the raw data - Apply
preTransformItem
functions (if defined) to each raw item - Apply the validation to the data (each item for
~Array
and~Object
variants) - Apply
postTransformItem
functions (if defined) to each validated item (ifcanonized
option istrue
, canonization will be done before this step) - Apply
postTransform
functions (if defined) to the final result before being stored in the valid item list
- For single validations,
preTransform
andpreTransformItem
are applied both, in that order. - For single validations,
postTransformItem
andpostTransform
are applied both, in that order. - If a transformation function fails (i.e. triggering an error), the validation fails (the data will be in
errors()
) without triggering any error
List of default validators
defined
The data will pass the validation if is not undefined
.
bool
The validation process will depend on the strict
option.
If the strict
is set to true
, it will pass the validation only if it's type is strictly a Boolean
.
If the strict
is set to false
, it will pass the validation always.
Also, its value will be set to the casting of the data (i.e. 0
will be false
, 1
true
).
In case of strings, it will evaluate to true
if it's not ''
, 'false'
or '0'
.
num
The validation process will depend on the strict
option.
When strict
is set to true
, it will only validate if it's a number
(isNumber).
If strict
is false
, it will accept also numeric values (isNumeric) and Infinity
.
It accepts also other validation options:
rangeMin
andrangeMax
: If any of this options is set, it will only accept values greater/less than the specified (as rangeMin < data < rangeMax).minEq
andmaxEq
: By default this options arefalse
, but if set totrue
, if setrangeMin
orrangeMax
will perform the comparisons with the<=
/>=
operators instead of<
/>
.regExp
: If this option is set (to a string or a valid RegExp), the data need to match it to pass thte validation.
There are also some options that don't accept the validation, but modificate the canonized value (when canonize
is true
):
integer
: when set totrue
the data will be converted to integer (before applying any other condition)min
andmax
: it will clamp the data to avoid outer values
Examples:
// Accept only numbers greater or equal than 10 and less than 20, which ends in ".0" or ".5"var v = rangeMin: 10 rangeMax: 20 minEq: true regExp: '\.[35]$';v // fail: it's less than 10 // fail: don't match the regular expression // fail: a number like this is passed as 10, not as 10.0 // pass: it's a string but strict is set to false by default (and preserves the decimal part) // fail: it doesn't match the regular expressoin // pass ; // fail: it's equal to rangeMax, but it's compared with < and not with <=
// accept all numeric values, setting them to 0 if negatives, and removing their decimal partvar v = integer: true min: 0;v // it will pass, and its value will be set to 0 // pass, there's no upper limit // pass and it's value will be set to 10 (integer) ; // pass and it's value will be set to -5
str
Accepts strings.
Like num
, its validation process depends on the strict
option: When true
it will only accept data of the string
type. If false
, it will accept all kind of data that can be converted to string
.
It accept also the following options:
minLength
: If specified, the data won't validate unless its length is greater or equal than this option.maxLength
: If specified, the data won't validate unless its length is less than this option.truncate
: Iftrue
the string will pass the validation, but will be truncated.append
: If specified AND the string is truncated, this string will be appended. Nothing is appended if the string length is less thanmaxLength
(see truncate).regExp
: If specified, it needs to match the RegExp to validate. It's applied aftertruncate
, but beforelowerCase
andupperCase
.lowerCase
: Iftrue
, the string will be transformed to lower case.upperCase
: Iftrue
, the string will be transformed to upper case.
Examples:
var v = returnNullOnErrors: false ;v ; v; // { // s1: "test string" // s3: "abcdefghij" // s4: "abcdefghij..." // s5: "abcde" // }v; // { // s0: '', // s2: "abcdefghijklmmnopqrstuvwxyz" // }
fn
This is a very simple validator that will pass the data only if they are functions. In this validator, the option strict
has no effect.
var v = ; v // pass, valid function ; // fail (it's a string, not a function)
enumerated
This validator checks that the passed data is one of the values defined in an object.
The strict
option defines if the comparison should be done strictly (===
) or not (==
).
You need to pass the object where the definitions are in the enumerated
option.
var weekDays = MON: 0 TUE: 1 WED: 2 THU: 3 FRI: 4 SAT: 5 SUN: 6 ;var v = enumerated: weekDays returnNullOnErrors: false ; v // fail: SUN is not a value of the enumerated (is a key) // fail: Ok this has nothing to do here... ; // fail: This value is not in the enumerated object v; // { e1: 0, e2: 4, e3: 3 }
enumeratedKey
This validator works like enumerated, but checks if the value is one of the keys of the object.
You need to pass the object where the definitions are in the enumerated
option.
var weekDays = MON: 0 TUE: 1 WED: 2 THU: 3 FRI: 4 SAT: 5 SUN: 6 ;var v = enumerated: weekDays returnNullOnErrors: false ; v // fail: 4 is a value, not a key // fail: this resolves to 3, which is not a key // fail: Ok this has nothing to do here... ; // fail: the key is defined as an upper case string v; // { e1: 'MON', e4: 'SUN' }
enumeratedKeyValue
This validator works the same that enumeratedKey, checking that the data is a key of the object, but returning its associated value instead of the key itself.
var weekDays = MON: 0 TUE: 1 WED: 2 THU: 3 FRI: 4 SAT: 5 SUN: 6 ;var v = enumerated: weekDays returnNullOnErrors: false ; v // fail: 4 is a value, not a key // fail: this resolves to 3, which is not a key // fail: Ok this has nothing to do here... ; // fail: the key is defined as an upper case string v; // { e1: 0, e4: 6 }
json
Validates data to be a correct JSON definition (using JSON.parse
).
Doesn't accept any option, and returns the parsed JavaScript data.
Note that functions and NaN
are not parseable by JSON
, so they are not supported,
and will fail the validation.
var v = ; v;vdata1; // 2
List of default aliases
notEmptyStr
Alias using str
, with default options to reject empty strings.
var v = returnNullOnErrors: false ; v ; v; // { s1: 'abcd', s2: ' ' }v; // { s3: '', n1: 2 }
positiveInt
Alias using num
, to accept only integers greater than 0
var v = returnNullOnErrors: false ; v ; v; // { n1: 123, n2: 123, n3: 1, f1: 1, f2: 6 }v; // { n4: 0, n5: -1, f3: 0.5, f4: -1.5 }
Defining custom validators
If you need a more complex validator, you can create your own too!
They can be created as global validators (defined in the prototype) with Validator.addValidator
or locally (defined in an instance v) with v.addValidator
A validator is just a function accepting two parameters and returning an object:
(data, options) => { data, valid }
- input:
data
is the data to validateoptions
is an object with the options specified when creating the validator or calling the method
- output:
data
is the canonized data (type casting, etc.)valid
is a Boolean saying if the data passes the validation
It's easier to understand with examples:
This validator will pass everything but the number 0
(and making use of the strict
option)
// validator definition { return data: data valid: optionsstrict && data !== 0 || !optionsstrict && data!= 0 ;} // validator addition (as a global definition called allButZero)Validator; // validator usage:v = returnNullOnErrors: false strict: false ;v ; v; // { n1: 1, n4: "0" }v; // { n2: 0, n3: "0" }
This other validator will accept only a list of comma-separated numbers whose addition is an even number.
If options.odd
is true
, it will pass the validation if the total is an odd number instead of even.
It will also convert the data to the said total.
// validator definition { var ok = true; var total = 0; var list; if typeof data !== 'string' ok = false; else list = data; list; if ok ok = total % 2 === optionsodd ? 1 : 0; return data: total valid: ok ;} // validator addition (as a global definition called sumEven)Validator; // validator usage:v = returnNullOnErrors: false ;v // 1 + 3 - 1 + 5 = 8 (even number: ok) // 1 + 2 + 4 = 7 (odd number: ok in this case) ; // -3 + 2 + 8 = 7 (odd number: fail) v; // { pass: 8, odd: 7 }v; // { fail: '-3,2,8' }
You can see more examples in definitions.js
Defining custom aliases
You can define your own aliases to call existing validators (or other aliases) with predefined options.
They can be created as global validators (defined in the prototype) with Validator.addAlias
or locally (defined in an instance v) with v.addAlias
var Validator = Validator; // define a global validator for phone numbers// (in Japan phone numbers are like XXX-XXXX-XXXX)var alias = 'phone';var validator = 'str';var options = regExp: /^\d{3}-\d{4}-\d{4}$/ ; // using the static function addAlias define the validator in the prototypeValidator; // now we can use it like this:var v1 = ;var v2 = ;v1 // this will validate ; // this won't validate typeof v1phone; // functiontypeof v2phone; // function // we can create a local validator too, like this:v1; // it won't be defined in the Validator.prototypetypeof v1int; // 'function'typeof v2int; // 'undefined'
You can see more examples in aliases.js
Defining and using schemas
A schema is nothing else than a set of validations. It's very useful when trying to validate the same set of data everytime (i.e. data to be stored in a database, or data for a data model coming from user input).
As the validators and aliases, a schema can be defined locally to a Validator instance, or globally to the Validator class itself.
var schemaDefinition = foo: validator: 'str' bar: validator: 'num' options: defaultValue: 0 ;var schemaOptions = optional: true; // defining a local validator schemavar v1 = ;var v2 = ;v1; // defining a global validator schemaValidator; // now we can use the schema like this:var data = foo: 'some text' bar: 123; // we can use the previously defined local schema in v1v1;v1; // { foo: 'some text', bar: 123 } // also, the global one in v1 and v2v1;v2; // but using a local schema in a different instance will throw an errorv2; // error // note that everytime we call .schema(), a .reset() call is done internally:v1;v1; // { foo: 'abc', bar: 123 }v1;v1; // { foo: 'abc', bar: 0 } // extra local options can also be passed to schema validationsv1;v1; // { foo: 'abc', bar: '123' }
Running tests
Install dev dependencies
npm install -d && npm test
Change log
1.1.0
- Added
preTransform
andpostTransform
optional callbacks to validators. - Fixed: default options behavior. Default options now get applied properly even if they change after defining a validator.
- Fixed:
allowOverwriteValidator
now works for aliases and schemas too. - Fixed: Schemas now use properly options specified at the definition time, and local options for each property validation.
- Added new schema options:
includeExternal
andexternalShouldFail
. - Added local options for schema validations (as a new 3rd parameter).