I'm developing a RESTful API with Node.js, Mongoose and Koa and I'm a bit stuck on what are the best practices when it comes to schemas and input validation.
Currently I have both a Mongoose and Joi schema for each resource. The Mongoose schema only includes the basic info about the specific resource. Example:
const UserSchema = new mongoose.Schema({
email: {
type: String,
lowercase: true,
},
firstName: String,
lastName: String,
phone: String,
city: String,
state: String,
country: String,
});
The Joi schema includes details about each property of the object:
{
email: Joi.string().email().required(),
firstName: Joi.string().min(2).max(50).required(),
lastName: Joi.string().min(2).max(50).required(),
phone: Joi.string().min(2).max(50).required(),
city: Joi.string().min(2).max(50).required(),
state: Joi.string().min(2).max(50).required(),
country: Joi.string().min(2).max(50).required(),
}
The Mongoose schema is used to create new instances of the given resource at endpoint handler level when writing to the database.
router.post('/', validate, routeHandler(async (ctx) => {
const userObj = new User(ctx.request.body);
const user = await userObj.save();
ctx.send(201, {
success: true,
user,
});
}));
The Joi schema is used in validation middleware to validate user input. I have 3 different Joi schemas for each resource, because the allowed input varies depending on the request method (POST, PUT, PATCH).
async function validate(ctx, next) {
const user = ctx.request.body;
const { method } = ctx.request;
const schema = schemas[method];
const { error } = Joi.validate(user, schema);
if (error) {
ctx.send(400, {
success: false,
error: 'Bad request',
message: error.details[0].message,
});
} else {
await next();
}
}
I am wondering if my current approach of using multiple Joi schemas on top of Mongoose is optimal, considering Mongoose also has built-int validation. If not, what would be some good practices to follow?
Thanks!