Parameter, query, form data validation and filtering for NodeJS.
Parameter, query, form data validation and filtering for Koa and Express.
See also this post about it on the Toptal Engineering Blog.
npm install --save datalize
const Koa = require('koa');
const Router = require('koa-router');
const datalize = require('datalize');
const field = datalize.field;
const app = new Koa();
// add any body parser
app.use(require('koa-body')());
const router = new Router();
router.post('/', datalize([
field('email', 'E-mail').required().email(),
field('firstname', 'Firstname').required(),
field('lastname', 'Lastname').required().trim(),
field('isTerms').bool(true),
]), (ctx, next) => {
ctx.body = {
status: 'success',
data: ctx.form,
};
});
app
.use(router.routes())
.use(router.allowedMethods());
const express = require('express');
const datalize = require('datalize');
const field = datalize.field;
const app = express();
// add any body parser
app.use(require('body-parser').json());
app.post('/', datalize([
field('email', 'E-mail').required().email(),
field('firstname', 'Firstname').required(),
field('lastname', 'Lastname').required().trim(),
field('isTerms').bool(true),
]), (req, res) => {
res.send({
status: 'success',
data: req.form,
});
});
Creates Data object and returns validation middleware, which uses body
as source. Result is set to context/request.form
object.
Same as datalize()
, but uses params
as source. Result is set to context/request.data
object.
Same as datalize()
, but uses query
as source. Result is set to context/request.data
object.
Returns: Field
Creates Field object.
Sets global option for datalize.
datalize.set('autoValidate', true);
Type: String
, Default: 'form'
Type: Boolean
, Default: true
If required error is returned, no other errors will be collected.
Type: Boolean
, Default: false
Auto validates form and throws Data.Error
if there is any error.
Type: Boolean
, Default: false
Auto converts field.array()
fields to array.
Type: Error
, Default: DataError
Error object thrown on autoValidate.
All filters and chainable.
field('rooms').required().int().range(1, 20)
condition
: can throw errorfilter
: updates valuecondition
condition
String|function
any
(optional) used only if nameOrFn is stringfilter
filter
String|function
any
(optional) used only if nameOrFn is stringfilter
filter
filter
Array
field.array()
.filter
condition
, filter
condition
, filter
Boolean
(optional)requiredValue
is provided, the field’s value must be equal to it.condition
, filter
Number
(optional)requiredValue
is provided, the field’s value must be equal to it.condition
any
filter
any
filter
condition
condition
, filter
filter
filter
filter
filter
Number
condition
, filter
Number|String|Function
(can be a number or name of a field or function that returns number)Number|String|Function
(can be a number or name of a field or function that returns number)condition
, filter
Number|String|Function
(can be a number or name of a field or function that returns number)condition
, filter
Number|String|Function
(can be a number or name of a field or function that returns number)condition
Number
Number
condition
Number
condition
Number
condition
, filter
condition
, filter
condition
, filter
condition
Array
filter
req.files
object.condition
Array
condition
Number
in Bytesfield.custom(function(value, result, ctx) {
if (['optionA', 'optionB'].indexOf(value) === -1) {
throw new Error('%s has invalid value.');
}
});
field.custom(function(value, result, ctx) {
return moment(value).format('YYYY/MM/DD');
});
field.custom(async (value, result, ctx) => {
const typeValue = await result.getValue('type');
if (type === 'business') {
return null;
}
});
const datalize = require('datalize');
const field = datalize.field;
datalize.Field.prototype.isSlug = function(chars = 'a-z-') {
const regexp = new RegExp(`^([${chars}]+)$`);
// make sure to return this.add() or this object to allow chaining
return this.add(function(value, result, ctx) {
if (!regexp.test(String(value))) {
throw new Error('%s contains invalid characters.');
}
});
};
// then the filter can be used anywhere
datalize([
field('slug').required().isSlug()
]);
router.post('/', datalize([
field('email', 'E-mail').required().email(),
]), (ctx, next) => {
if (!ctx.form.isValid) {
ctx.status = 400;
ctx.body = {
status: 'error',
errors: ctx.form.errors,
};
return;
}
ctx.body = {
status: 'success',
data: ctx.form,
};
});
datalize.set('autoValidate', true);
// add to very beginning of koa middlewares
app.use(async (ctx, next) => {
try {
await next();
} catch (err) {
if (err instanceof datalize.Error) {
ctx.status = 400;
ctx.body = Object.assign({
status: 'error'
}, err.toJSON());
}
}
});
datalize.set('autoValidate', true);
// add to very end of express middlewares
app.use(function(err, req, res, next) {
if (err instanceof datalize.Error) {
res.status(400).send(Object.assign({
status: 'error'
}, err.toJSON()));
}
});
MIT
Copyright © 2018 Andrej Adamcik