Do you think validate types in JavaScript is boring?
Have you heard about Yup? It's an amazing JavaScript lib to validate schemas!
Let's imagine:
We have a list products
endpoint, which takes the page number
and limit
as arguments from querystring
//productApi.js
const { Router } = require('express');
const productController = require('./controller');
const router = new Router();
module.exports = app => app.use('/products', router);
router.get('/', (req, res, next) => {
const { page, limit } = req.query;
if (isNaN(page) || isNaN(limit)) return res.status(400).end();
productController.list({ page: Number(page), limit: Number(limit) })
.then(products => res.json(products))
.catch(error => res.status(400).json({ error }));
}
The problem is: page
and limit
can be undefined
and... anything else
... it's javascript baby.
A very efficient way is to create a middleware to validate your params using Yup.
//validate.js
const yup = require('yup');
module.exports = ({ shape, path = 'query' }) => async (req, res, next) => {
const schema = yup.object().shape(shape);
try {
const validData = await schema.validate(req[path]);
req.validData = validData;
return next();
} catch (error) {
return res.status(400).json({ error });
}
};
After then, use on route
//productApi.js
const { Router } = require('express');
const yup = require('yup');
const validate = require('./validate');
const productController = require('./controller');
const router = new Router();
module.exports = app => app.use('/products', router);
router.get(
'/',
validate({
shape: {
page: yup.number().default(0),
limit: yup.number().default(15),
}
}),
(req, res, next) => {
productController
.list(req.validData)
.then(products => res.json(products))
.catch(error => res.status(400).json({ error }));
},
);
Of course you can create complex schemas with Yup. It works as you need.
I hope it helps someone!
Oldest comments (10)
Awesome tips bro!
That implementation using on routes was really cool! I have seen people using Joi, though, never heard of Yup. Gonna check it out later.
Yup's api/style was inspired by Joi!
Awesome post João, thanks!
I've used Joi but it's pretty sluggish depending on the validation rules you need to implement. I've stumbled across github.com/icebob/fastest-validator, which is my go-to Javascript "spec/schema" definition package at the moment.
Glad to read this!
I never heard about
fastest-validator
before. Thanks for share! Seems to be really fast 😱how are you using this with express routes? middleware? mind sharing how your middleware looks
You need to make a manual middleware passing the schema, just as a custom middleware for joi/yup/express-validator, etc.
Other middlewares (like celebrate) might add extra features like distinct body, query and params validation.
Thanks, it helps me a lot.
nice post! how do you validate query params and body at the same time using your middleware
You'd need to create a custom middleware, validate, sanitize and pass everything over to the route, or you can search for middlewares in npm.