Express Joi Validations
express-joi-validations is an Express.js middleware package designed to streamline request validation using the Joi schema validation library. Currently at version 0.1.0, it provides a flexible mechanism to validate various parts of an incoming HTTP request, including headers, URL parameters, query strings, and the request body. While its last publish was over two years ago (as of May 2024), suggesting a maintenance-only status rather than active development, it offers both a consolidated validation middleware for multiple request parts and individual helper functions (e.g., `validateBody`, `validateParams`) for more granular control. Key differentiators include its explicit handling of validated data through `request.validationValues` and the ability to optionally overwrite the original request data or throw errors for integration with asynchronous error handling. This allows developers to strictly enforce data integrity at the API layer.
Common errors
-
JoiValidationError: "body" is not allowed to be empty
cause An empty request body was sent, but the Joi schema for `body` marked all fields as required, or didn't allow for an empty object.fixEnsure that the client sends a non-empty request body if required by the schema, or update the Joi schema to allow optional fields or an empty object using `.optional()` or `.allow({})`. -
TypeError: Cannot read properties of undefined (reading 'isJoi')
cause This typically occurs if the error handling middleware expects a Joi error structure but receives a different type of error, often because `throwErrors` was not set to `true`.fixVerify that `throwErrors: true` is configured where validation is performed, allowing the `express-joi-validations` middleware to throw Joi-specific errors that your error handler can then catch and process. -
Error: Invalid Joi Schema
cause The Joi schema object passed to a validation helper (e.g., `validateBody`) is not a valid Joi schema instance.fixEnsure that the schema is correctly defined using `Joi.object({})`, `Joi.string()`, etc., and is a valid Joi schema object before passing it to the validation middleware.
Warnings
- gotcha By default, validation errors are not thrown. Instead, they are attached to `request.validationErrors`. To throw errors for standard Express error handling, you must set the `throwErrors: true` option during middleware initialization or per helper function.
- gotcha The package can optionally overwrite the original `req.body`, `req.query`, etc., with the validated data. If `overwriteRequest` is `false` (default), validated data is available in `request.validationValues`, requiring explicit access or type assertions in TypeScript.
- gotcha This package is at version 0.1.0 and has not been updated in over two years (as of May 2024). Compatibility with newer versions of Joi or Express, especially those introducing breaking changes, might not be actively maintained, potentially leading to unexpected behavior or security vulnerabilities with future dependency updates.
Install
-
npm install express-joi-validations -
yarn add express-joi-validations -
pnpm add express-joi-validations
Imports
- validate
const validate = require('express-joi-validations');import validate from 'express-joi-validations';
- expressJoiValidations
const { expressJoiValidations } = require('express-joi-validations');import { expressJoiValidations } from 'express-joi-validations'; - validateBody
import validateBody from 'express-joi-validations/validateBody';
import { validateBody } from 'express-joi-validations'; - Joi
import Joi from 'joi';
import { Joi } from 'express-joi-validations';
Quickstart
import express, { Request, Response, NextFunction } from 'express';
import { Joi, validateHeaders, validateParams, validateBody, expressJoiValidations } from 'express-joi-validations';
const app = express();
app.use(express.json()); // Required to parse JSON request bodies
// Optionally configure global settings for all validations
app.use(expressJoiValidations({ throwErrors: true, overwriteRequest: false }));
const userToken = Joi.object({
authorization: Joi.string().regex(/^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_.+/=]*$/).required(),
});
const postId = Joi.object({
id: Joi.string().hex().length(24).required(),
});
const postBody = Joi.object({
title: Joi.string().required().trim().min(5),
content: Joi.string().required().trim().min(10),
tags: Joi.array().items(Joi.string()).optional()
});
// Example route with chained validations
app.put(
'/posts/:id',
validateHeaders(userToken),
validateParams(postId),
validateBody(postBody, { allowUnknown: false }), // Joi options can be passed per validator
(req: Request, res: Response) => {
// If throwErrors is true, an error handler middleware will catch validation errors.
// Otherwise, validation results (errors, values) are on req.validationErrors and req.validationValues
const validatedData = (req as any).validationValues; // Cast to 'any' or extend Request type if not using `overwriteRequest`
res.status(200).json({ message: 'Post updated successfully', data: validatedData });
}
);
// Global error handler for thrown validation errors (if throwErrors: true)
app.use((err: any, req: Request, res: Response, next: NextFunction) => {
if (err && err.error && err.error.isJoi) {
// A Joi validation error
return res.status(400).json({ type: err.type, message: err.error.toString() });
}
next(err); // Pass on to other error handlers
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));