Valify was created to easily validate data structures. With a simple syntax it is ideal in many contexts for example in REST API
Documentation
- Installation
- Basic usage
- Model options
- Field options
- Error object
- Default values
- Nested models
- Promises
- Detect unknown fields
- Auto cast
- Manipulate data
- Immutability
- Undefined values
- Define custom types
- Locale
- Types
- Upgrade to V4
npm install --save valify
<script src="https://unpkg.com/valify/dist/valify.min.js"></script>
const Valify = require('valify');
// Define a model
const userModel = new Valify({
firstName: 'string',
lastName: 'string',
age: 'int?', // this is not required
role: {
type: 'string',
default: 'editor'
},
colors: ['string'],
createdAt: {
type: 'date',
default: new Date()
}
});
// A data object
const data = {
firstName: 'Mike',
lastName: 'Ricali',
role: 'owner',
colors: ['red', 'yellow', 'orange']
};
// Validate userModel
try {
userModel(data);
} catch(e) {
console.log(e.message, e.fields);
}
Property | Type | Default | Description |
---|---|---|---|
usePromise |
boolean |
false |
If you need to use with Promise must just add usePromise to model settings. Details |
detectUnknown |
boolean |
false |
If you need to define a strict model where all the fields correspond to those defined, you can set detectUnknown to true. Details |
autoCast |
boolean |
false |
Sometimes you may need to cast a string (where possible) to a primitive type. You can set autoCast to true. Details |
returnImmutable |
boolean |
false |
Valify model returns also the data that you have passed for the validation, if you want an immutable data, set returnImmutable to true. Details |
overwriteUndefined |
boolean |
false |
If you need manage undefined value with a default value, set overwriteUndefined to true, obviously works only if default is set. Details |
appendToError |
object |
{} | If you need to add custom properties to error stack |
Property | Type | Default | Description |
---|---|---|---|
type |
object ,array ,string ,function |
null |
Type of control |
required |
boolean |
true |
Indicates if the field is required |
default |
any |
null |
Default value |
allowNull |
boolean |
false |
Allow null value, overwrites all checks |
allowEmpty |
boolean |
true |
Allow empty value, works for string , array and object |
locale |
object |
object |
An object that contains locale strings that overwrites those globals |
convert |
function |
null |
A function to manipulate/conversion data |
onError |
function |
null |
A function triggered when an check fails |
Valify in case of errors returns an object with 2 properties:
message
is the first error occurredfields
is an array of all errors occurred
{
message: '"aParam.other.lastName" is required',
fields: [
{
path: 'aParam.other.lastName',
message: '"aParam.other.lastName" is required',
field: 'lastName',
type: 'string'
}
]
}
You can set a default value for each field, this setting overwrites required
property to false
.
const Valify = require('valify');
// Define a model
const userModel = new Valify({
name: 'string',
role: {
type: 'string',
default: 'editor'
}
});
// A data object
const data = {
name: 'Mike Ricali'
};
try {
userModel(data); //=> {name: 'Mike Ricali'}
} catch(e) {
console.log(e.message, e.fields);
}
It's possible also add nested model, for example you could have an array field like below:
const userModel = new Valify({
firstName: 'string',
lastName: 'string',
records: [
new Valify({
id: 'int',
accessOn: 'date',
otherNested: new Valify({
color: 'string'
})
})
]
});
// A data object
const data = {
firstName: 'Mike',
lastName: 'Ricali',
records: [
{
id: 1,
accessOn: '2017-12-23T00:01:00',
otherNested: {
color: 'red'
}
},
{
id: 2,
accessOn: '2017-12-23T00:02:00',
otherNested: {
color: 'yellow'
}
},
{
id: 3,
accessOn: '2017-12-23T00:03:00',
otherNested: {
color: 'green'
}
}
]
};
// Validate userModel
try {
userModel(data);
} catch(e) {
console.log(e.message, e.fields);
}
If you need to use with Promise must just add usePromise
to model settings.
// Define a model
const userModel = new Valify({
firstName: {
type: 'string',
required: true
},
lastName: {
type: 'string',
required: true
}
}, {
usePromise: true
});
// A data object
const data = {
firstName: 'Mike'
};
// Validate userModel
userModel(data).then(()=>{
console.log('ok');
}).catch(e => {
console.log(e);
// An object like below
/*
{
message: 'lastName is required',
fields: [{field: 'lastName', message: 'lastName is required', path: 'lastName'}]
}
*/
});
If you need to define a strict model where all the fields correspond to those defined, you can set detectUnknown
to true.
const userModel = new Valify({
firstName: 'string',
lastName: 'string',
email: 'email'
}, {
detectUnknown: true
});
try {
userModel({
firstName: 'Mike',
lastName: 'Storm',
email: '[email protected]',
role: 'admin',
age: 26,
})
} catch (e) {
console.log(e.message); //Unknown fields were detected: role, age
}
Sometimes you may need to cast a string (where possible) to a primitive type. You can set autoCast
to true.
const userModel = new Valify({
firstName: 'string',
lastName: 'string',
email: 'email',
aBoolean: 'boolean',
aNumber: 'number',
aUndefined: 'undefined',
aNull: 'null'
}, {
autoCast: true
});
try {
userModel({
firstName: 'Mike',
lastName: 'Storm',
email: '[email protected]',
role: 'admin',
aBoolean: 'true',
aNumber: '52',
aUndefined: 'undefined',
aNull: 'null'
})
//... done
} catch (e) {
}
You may need to manipulate data before the validation.
// Define a model
const userModel = new Valify({
firstName: {
type: 'string',
convert: value => value.toUpperCase()
},
lastName: {
type: 'string',
convert: value => value.toUpperCase()
},
age: {
type: 'number',
convert: value => parseInt(value)
}
});
// A data object
const data = {
firstName: 'Mike',
lastName: 'Ricali',
age: '25'
};
userModel(data);
console.log(data.firstName, data.lastName, data.age, typeof data.age); //=> MIKE RICALI 25 number
- Convert function returns:
value
, current valuedata
, a copy of origin data objectbe
, a library used for several validations. More info on beJS
Valify model returns also the data that you have passed for the validation, if you want an immutable data, set returnImmutable
to true.
const userModel = new Valify({
firstName: 'string',
lastName: {
type: 'string',
convert: value => value.toUpperCase()
},
email: 'email'
}, {returnImmutable: true});
const data = {
firstName: 'Mike',
lastName: 'Storm',
email: '[email protected]'
};
const newData = userModel(data);
console.log(data.lastName, newData.lastName);
//=> Storm, STORM
If you need manage undefined value with a default value, set overwriteUndefined
to true, obviously works only if default
is set.
const userModel = new Valify({
aNumber: 'int',
lastName: {
type: 'string',
default: 'Mike'
}
},{
overwriteUndefined: true
});
const a = ['hello'];
try {
userModel({
aNumber: 24,
lastName: a[1] //=> index at 1 is undefined but will be applied default value "mike"
});
done();
} catch (e) {}
There are different ways to define custom types:
Valify.addType('mycustom1', (value, data) => {
console.log(data);
return value === 10;
});
// it's also possible returns a string as error like below
Valify.addType('mycustom2', (value) => {
if (value !== 10)
return 'ops... must be 10'
});
// One method to add several types
Valify.addTypes([
{
name: 'mycustom3',
fn: value => value === 'hello'
},
{
name: 'mycustom4',
fn: value => value === 'world'
}
]);
// Define a model
const userModel = new Valify({
aNumber: 'mycustom1',
otherNumber: 'mycustom2'
});
// A data object
const data = {
aNumber: 9,
otherNumber: 11,
};
try {
userModel(data);
} catch(e) {
console.log(e.message, e.fields);
}
// Define a model
const userModel = new Valify({
aString: {
type: value => typeof value === 'string'
},
// or
aBoolean: value => typeof value === 'boolean'
});
// A data object
const data = {
aString: 'hello',
aBoolean: 5
};
try {
userModel(data);
} catch(e) {
console.log(e.message, e.fields);
}
If you need to define multiple checks in one type, you can do this:
new Valify({
myString: value => {
if (typeof value !== 'string')
return 'must be a string';
if (value.length < 5)
return 'must be greater than 5 chars';
if (value.length > 10)
return 'must be less than 10 chars';
}
})
- Inside all custom type function are passed 3 arguments:
value
, current valuedata
, a copy of origin data objectbe
, a library used for several validations. More info on beJS
Example
new Valify({
color0: 'string',
color1: (value, data, be) => {
if (!be.string(value))
return 'must be a string';
if (value === data.color0)
return 'must be different of color0';
}
})
You can set locale string in two ways:
Valify.setLocale({
TYPE_FAIL: 'this type has failed'
});
Default strings
Name | Default |
---|---|
UNKNOWN_TYPE |
Unknown type: "{type}" |
TYPE_FAIL |
"{path}" expects "{type}" but receives: {dataField} |
TYPE_ARRAY_FAIL |
"{path}" expects array of "{type}" but receives: {dataField} |
TYPE_FUNCTION_FAIL |
"{path}" receives: {dataField} |
FIELD_REQUIRED |
"{path}" is required |
DATA_REQUIRED |
Data is required and must be an object |
FIELD_CANNOT_EMPTY |
"{path}" cannot be empty |
UNKNOWN_DETECTED |
Unknown fields were detected: {unknown} |
// Define a model
const userModel = new Valify({
aString: {
type: 'string',
locale: {
TYPE_FAIL: 'this type has failed'
}
}
});
- There are only two available properties:
TYPE_FAIL
TYPE_ARRAY_FAIL
FIELD_REQUIRED
FIELD_CANNOT_EMPTY
All types that you can use:
-
JavaScript standard
arguments
array
boolean
buffer
date
error
float32array
float64array
function
generatorfunction
int16array
int32array
int8array
map
null
number
object
promise
regexp
set
string
symbol
uint16array
uint32array
uint8array
uint8clampedarray
undefined
weakmap
weakset
-
Extra
alpha
alphanumeric
any
datestring
email
float
int
ip
timestring
uuid
url
- Breaking changes
- Changed in locale strings {field} with {path}
- Changed
convert
position, now is before all checks - Removed validators, use custom types instead
You can view the changelog here
Valify is open-sourced software licensed under the MIT license