Joi : data validation library

Kepler·2020년 9월 21일
0

Usage

In the new portal project, we implemented a validator to check whether the request data received from the client's request was in an acceptable format to be inserted into our database.

A validator makes CRUD safer and more efficient since it can reject the input data, even before it even hits the controller, and make sure that only the correctly formated data with all necessary information are received.

Also, in this way, your code is cleaner and more modularized, since you put all validation logic in a separate file.

Joi

Joi is a very easy-to-use and well-documented library provided by Walmart(!).

Installation

npm i joi

Directory structrue

Joi is used as a middleware for each route. So, for example, it can go inside middleware inside routes

Setup

const router = require("express").Router()
const controller = require("../controllers/controller")

const validator = require("express-joi-validation").createValidator({
  passError: true,
}) //[1]
const validatorFile = require("./middleware/validators/validator") //[2]

router.post(
  "/post_something",
  ...other middlewares,
  validator.body(validatorFile.someSchema),
  controller.someController
) // [3]

[1] Creates an instance of validator module that can be used to generate middleware.
[2] Import the validator file
[3] Based on what part of request you want to validate, change .body part to .params , .query and etc.

Schema

// Example1: Validation for object id
const JoiBase = require("@hapi/joi")
const JoiDate = require("@hapi/joi-date") 
const { isValidObjectId } = require("mongoose")

const Joi = JoiBase.extend(JoiDate)

module.exports.objectIdArraySchema = Joi.object({
  id: Joi.array()
    .items(
      Joi.string().custom(
        (val, helpers) =>
          !isValidObjectId(val)
            ? helpers.message("Value must be a valid object Id")
            : val,
        "object Id validation"
      )
    )
    .required(),
})

// Example2: Validation for integer
module.exports.numberSchema = Joi.object({
  number: Joi.number().min(0).max(3),
  limit: Joi.number()
    .default(300)
    .min(1)
    .max(1000)
    .message("Limit must be a value from 1 to 1000."),
  offset: Joi.number()
    .default(0)
    .min(0)
    .message("Offset must be a value greater than or equal to zero."),
})

// Example3: Validation for many stuff
const someSchema = {
    something: Joi.array()
      .items(
        Joi.alternatives().try(
          Joi.string().alphanum().length(24),
          Joi.object({
            _id: Joi.string().alphanum().length(24),
            name: Joi.string(),
            description: Joi.string(),
            url: Joi.string(),
          })
        )
      )
      .required(),
  name: Joi.string().trim().allow(""),
  location: Joi.object({
    country: Joi.string().trim().allow(""),
    continent: Joi.string().trim().allow(""),
  }),
  updated_at: Joi.date().format("YYYY-MM-DDTHH:mm:ss.SSSZ").raw(),
}

module.exports.someOtherSchema = Joi.object({
  type_1: Joi.array().items(Joi.string().trim().required()),
  type_2: Joi.array().items(Joi.binary().required()),
Joi.array().items(Joi.boolean().optional()).optional(),
}).nand("type_1", "type_2").options({ stripUnknown: true }
  • joi-date module is used for formatting date.
  • stripUnknown is used if you want to remove the unknown keys received in request.
  • .nand method if one of fields is required
  • alternatives(): Generates a type that will match one of the provided alternative schemas via the try() method.
  • .custom(method, [description]):
profile
🔰

0개의 댓글