{"id":17668492,"url":"https://github.com/evanshortiss/express-joi-validation","last_synced_at":"2025-05-16T05:04:16.754Z","repository":{"id":41545409,"uuid":"88107405","full_name":"evanshortiss/express-joi-validation","owner":"evanshortiss","description":"validate express application inputs and parameters using joi","archived":false,"fork":false,"pushed_at":"2024-12-13T07:47:00.000Z","size":86,"stargazers_count":101,"open_issues_count":10,"forks_count":22,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-08T15:11:45.802Z","etag":null,"topics":["express","express-middleware","express-validation","joi","middleware","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/evanshortiss.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-04-13T00:09:14.000Z","updated_at":"2025-03-29T16:25:51.000Z","dependencies_parsed_at":"2025-01-20T00:02:46.624Z","dependency_job_id":"bc160b4d-6e1e-4a54-8d16-f503a9a7fa01","html_url":"https://github.com/evanshortiss/express-joi-validation","commit_stats":{"total_commits":53,"total_committers":9,"mean_commits":5.888888888888889,"dds":"0.16981132075471694","last_synced_commit":"8b08da1ba4fafafad6db05009a3770027ad5afa6"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanshortiss%2Fexpress-joi-validation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanshortiss%2Fexpress-joi-validation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanshortiss%2Fexpress-joi-validation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evanshortiss%2Fexpress-joi-validation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/evanshortiss","download_url":"https://codeload.github.com/evanshortiss/express-joi-validation/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254471061,"owners_count":22076585,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["express","express-middleware","express-validation","joi","middleware","typescript"],"created_at":"2024-10-23T23:22:45.927Z","updated_at":"2025-05-16T05:04:16.734Z","avatar_url":"https://github.com/evanshortiss.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# express-joi-validation\n\n![TravisCI](https://travis-ci.org/evanshortiss/express-joi-validation.svg)\n[![Coverage Status](https://coveralls.io/repos/github/evanshortiss/express-joi-validation/badge.svg?branch=master)](https://coveralls.io/github/evanshortiss/express-joi-validation?branch=master)\n[![npm version](https://badge.fury.io/js/express-joi-validation.svg)](https://www.npmjs.com/package/express-joi-validation)\n[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-blue.svg)](http://www.typescriptlang.org/)\n[![npm downloads](https://img.shields.io/npm/dm/express-joi-validation.svg?style=flat)](https://www.npmjs.com/package/express-joi-validation)\n[![Known Vulnerabilities](https://snyk.io//test/github/evanshortiss/express-joi-validation/badge.svg?targetFile=package.json)](https://snyk.io//test/github/evanshortiss/express-joi-validation?targetFile=package.json)\n\nA middleware for validating express inputs using Joi schemas. Features include:\n\n* TypeScript support.\n* Specify the order in which request inputs are validated.\n* Replaces the incoming `req.body`, `req.query`, etc and with the validated result \n* Retains the original `req.body` inside a new property named `req.originalBody`.\n. The same applies for headers, query, and params using the `original` prefix,\ne.g `req.originalQuery`\n* Chooses sensible default Joi options for headers, params, query, and body.\n* Uses `peerDependencies` to get a Joi instance of your choosing instead of\nusing a fixed version.\n\n## Quick Links\n\n* [API](#api)\n* [Usage (JavaScript)](#usage-javascript)\n* [Usage (TypeScript)](#usage-typescript)\n* [Behaviours](#behaviours)\n  * [Joi Versioning](#joi-versioning)\n  * [Validation Ordering](#validation-ordering)\n  * [Error Handling](#error-handling)\n  * [Joi Options](#joi-options)\n  * [Custom Express Error Handler](#custom-express-error-handler)\n\n## Install\n\nYou need to install `joi` with this module since it relies on it in\n`peerDependencies`.\n\n```\nnpm i express-joi-validation joi --save\n```\n\n## Example\nA JavaScript and TypeScript example can be found in the `example/` folder of\nthis repository.\n\n## Usage (JavaScript)\n\n```js\nconst Joi = require('joi')\nconst app = require('express')()\nconst validator = require('express-joi-validation').createValidator({})\n\nconst querySchema = Joi.object({\n  name: Joi.string().required()\n})\n\napp.get('/orders', validator.query(querySchema), (req, res) =\u003e {\n  // If we're in here then the query was valid!  \n  res.end(`Hello ${req.query.name}!`)\n})\n```\n\n## Usage (TypeScript)\n\nFor TypeScript a helper `ValidatedRequest` and\n`ValidatedRequestWithRawInputsAndFields` type is provided. This extends the\n`express.Request` type and allows you to pass a schema using generics to\nensure type safety in your handler function.\n\n```ts\nimport * as Joi from 'joi'\nimport * as express from 'express'\nimport {\n  ContainerTypes,\n  // Use this as a replacement for express.Request\n  ValidatedRequest,\n  // Extend from this to define a valid schema type/interface\n  ValidatedRequestSchema,\n  // Creates a validator that generates middlewares\n  createValidator\n} from 'express-joi-validation'\n\nconst app = express()\nconst validator = createValidator()\n\nconst querySchema = Joi.object({\n  name: Joi.string().required()\n})\n\ninterface HelloRequestSchema extends ValidatedRequestSchema {\n  [ContainerTypes.Query]: {\n    name: string\n  }\n}\n\napp.get(\n  '/hello',\n  validator.query(querySchema),\n  (req: ValidatedRequest\u003cHelloRequestSchema\u003e, res) =\u003e {\n    // Woohoo, type safety and intellisense for req.query!\n    res.end(`Hello ${req.query.name}!`)\n  }\n)\n```\n\nYou can minimise some duplication by using [joi-extract-type](https://github.com/TCMiranda/joi-extract-type/).\n\n_NOTE: this does not work with Joi v16+ at the moment. See [this issue](https://github.com/TCMiranda/joi-extract-type/issues/23)._\n\n```ts\nimport * as Joi from 'joi'\nimport * as express from 'express'\nimport {\n  // Use this as a replacement for express.Request\n  ValidatedRequest,\n  // Extend from this to define a valid schema type/interface\n  ValidatedRequestSchema,\n  // Creates a validator that generates middlewares\n  createValidator\n} from 'express-joi-validation'\n\n// This is optional, but without it you need to manually generate\n// a type or interface for ValidatedRequestSchema members\nimport 'joi-extract-type'\n\nconst app = express()\nconst validator = createValidator()\n\nconst querySchema = Joi.object({\n  name: Joi.string().required()\n})\n\ninterface HelloRequestSchema extends ValidatedRequestSchema {\n  [ContainerTypes.Query]: Joi.extractType\u003ctypeof querySchema\u003e\n\n  // Without Joi.extractType you would do this:\n  // query: {\n  //   name: string\n  // }\n}\n\napp.get(\n  '/hello',\n  validator.query(querySchema),\n  (req: ValidatedRequest\u003cHelloRequestSchema\u003e, res) =\u003e {\n    // Woohoo, type safety and intellisense for req.query!\n    res.end(`Hello ${req.query.name}!`)\n  }\n)\n```\n\n## API\n\n### Structure\n\n* module (express-joi-validation)\n  * [createValidator(config)](#createvalidatorconfig)\n    * [query(options)](#validatorqueryschema-options)\n    * [body(options)](#validatorbodyschema-options)\n    * [headers(options)](#validatorheadersschema-options)\n    * [params(options)](#validatorparamsschema-options)\n    * [response(options)](#validatorresponseschema-options)\n    * [fields(options)](#validatorfieldsschema-options)\n\n### createValidator(config)\nCreates a validator. Supports the following options:\n\n* passError (default: `false`) - Passes validation errors to the express error\nhander using `next(err)` when `true`\n* statusCode (default: `400`) - The status code used when validation fails and\n`passError` is `false`.\n\n#### validator.query(schema, [options])\nCreates a middleware instance that will validate the `req.query` for an\nincoming request. Can be passed `options` that override the config passed\nwhen the validator was created.\n\nSupported options are:\n\n* joi - Custom options to pass to `Joi.validate`.\n* passError - Same as above.\n* statusCode - Same as above.\n\n#### validator.body(schema, [options])\nCreates a middleware instance that will validate the `req.body` for an incoming\nrequest. Can be passed `options` that override the options passed when the\nvalidator was created.\n\nSupported options are the same as `validator.query`.\n\n#### validator.headers(schema, [options])\nCreates a middleware instance that will validate the `req.headers` for an\nincoming request. Can be passed `options` that override the options passed\nwhen the validator was created.\n\nSupported options are the same as `validator.query`.\n\n#### validator.params(schema, [options])\nCreates a middleware instance that will validate the `req.params` for an\nincoming request. Can be passed `options` that override the options passed\nwhen the validator was created.\n\nSupported options are the same as `validator.query`.\n\n#### validator.response(schema, [options])\nCreates a middleware instance that will validate the outgoing response.\nCan be passed `options` that override the options passed when the instance was\ncreated.\n\nSupported options are the same as `validator.query`.\n\n#### validator.fields(schema, [options])\nCreates a middleware instance that will validate the fields for an incoming\nrequest. This is designed for use with `express-formidable`. Can be passed\n`options` that override the options passed when the validator was created.\n\nThe `instance.params` middleware is a little different to the others. It _must_\nbe attached directly to the route it is related to. Here's a sample:\n\n```js\nconst schema = Joi.object({\n  id: Joi.number().integer().required()\n});\n\n// INCORRECT\napp.use(validator.params(schema));\napp.get('/orders/:id', (req, res, next) =\u003e {\n  // The \"id\" parameter will NOT have been validated here!\n});\n\n// CORRECT\napp.get('/orders/:id', validator.params(schema), (req, res, next) =\u003e {\n  // This WILL have a validated \"id\"\n})\n```\n\nSupported options are the same as `validator.query`.\n\n## Behaviours\n\n### Joi Versioning\nThis module uses `peerDependencies` for the Joi version being used.\nThis means whatever `joi` version is in the `dependencies` of your\n`package.json` will be used by this module.\n\n\n### Validation Ordering\nValidation can be performed in a specific order using standard express\nmiddleware behaviour. Pass the middleware in the desired order.\n\nHere's an example where the order is headers, body, query:\n\n```js\nroute.get(\n  '/tickets',\n  validator.headers(headerSchema),\n  validator.body(bodySchema),\n  validator.query(querySchema),\n  routeHandler\n);\n```\n\n### Error Handling\nWhen validation fails, this module will default to returning a HTTP 400 with\nthe Joi validation error as a `text/plain` response type.\n\nA `passError` option is supported to override this behaviour. This option\nforces the middleware to pass the error to the express error handler using the\nstandard `next` function behaviour.\n\nSee the [Custom Express Error Handler](#custom-express-error-handler) section\nfor an example.\n\n### Joi Options\nIt is possible to pass specific Joi options to each validator like so:\n\n```js\nroute.get(\n  '/tickets',\n  validator.headers(\n    headerSchema,\n    {\n      joi: {convert: true, allowUnknown: true}\n    }\n  ),\n  validator.body(\n    bodySchema,\n    {\n      joi: {convert: true, allowUnknown: false}\n    }\n  )\n  routeHandler\n);\n```\n\nThe following sensible defaults for Joi are applied if none are passed:\n\n#### Query\n* convert: true\n* allowUnknown: false\n* abortEarly: false\n\n#### Body\n* convert: true\n* allowUnknown: false\n* abortEarly: false\n\n#### Headers\n* convert: true\n* allowUnknown: true\n* stripUnknown: false\n* abortEarly: false\n\n#### Route Params\n* convert: true\n* allowUnknown: false\n* abortEarly: false\n\n#### Fields (with express-formidable)\n* convert: true\n* allowUnknown: false\n* abortEarly: false\n\n\n## Custom Express Error Handler\n\n```js\nconst validator = require('express-joi-validation').createValidator({\n  // This options forces validation to pass any errors the express\n  // error handler instead of generating a 400 error\n  passError: true\n});\n\nconst app = require('express')();\nconst orders = require('lib/orders');\n\napp.get('/orders', validator.query(require('./query-schema')), (req, res, next) =\u003e {\n  // if we're in here then the query was valid!\n  orders.getForQuery(req.query)\n    .then((listOfOrders) =\u003e res.json(listOfOrders))\n    .catch(next);\n});\n\n// After your routes add a standard express error handler. This will be passed the Joi\n// error, plus an extra \"type\" field so we can tell what type of validation failed\napp.use((err, req, res, next) =\u003e {\n  if (err \u0026\u0026 err.error \u0026\u0026 err.error.isJoi) {\n    // we had a joi error, let's return a custom 400 json response\n    res.status(400).json({\n      type: err.type, // will be \"query\" here, but could be \"headers\", \"body\", or \"params\"\n      message: err.error.toString()\n    });\n  } else {\n    // pass on to another error handler\n    next(err);\n  }\n});\n```\n\nIn TypeScript environments `err.type` can be verified against the exported\n`ContainerTypes`:\n\n```ts\nimport { ContainerTypes } from 'express-joi-validation'\n\napp.use((err: any|ExpressJoiError, req: express.Request, res: express.Response, next: express.NextFunction) =\u003e {\n  // ContainerTypes is an enum exported by this module. It contains strings\n  // such as \"body\", \"headers\", \"query\"...\n  if (err \u0026\u0026 err.type in ContainerTypes) {\n    const e: ExpressJoiError = err\n    // e.g \"you submitted a bad query paramater\"\n    res.status(400).end(`You submitted a bad ${e.type} paramater`)\n  } else {\n    res.status(500).end('internal server error')\n  }\n})\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevanshortiss%2Fexpress-joi-validation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevanshortiss%2Fexpress-joi-validation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevanshortiss%2Fexpress-joi-validation/lists"}