{"id":30675157,"url":"https://github.com/gsmithun4/expressjs-field-validator","last_synced_at":"2026-03-06T21:12:12.054Z","repository":{"id":33971284,"uuid":"164423959","full_name":"gsmithun4/expressjs-field-validator","owner":"gsmithun4","description":"Plugin for validating JSON request, middleware for expressjs","archived":false,"fork":false,"pushed_at":"2026-03-04T12:39:47.000Z","size":718,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-04T17:47:32.176Z","etag":null,"topics":["data","express-js","expressjs","json-request","middleware","nodejs","request","rest-api","validation"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gsmithun4.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-01-07T11:39:38.000Z","updated_at":"2026-03-04T12:39:39.000Z","dependencies_parsed_at":"2024-01-07T16:22:05.931Z","dependency_job_id":null,"html_url":"https://github.com/gsmithun4/expressjs-field-validator","commit_stats":{"total_commits":109,"total_committers":4,"mean_commits":27.25,"dds":0.3027522935779816,"last_synced_commit":"779c9dce86b4826ca0c8f39b0cc08054cfc1d68d"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/gsmithun4/expressjs-field-validator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gsmithun4%2Fexpressjs-field-validator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gsmithun4%2Fexpressjs-field-validator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gsmithun4%2Fexpressjs-field-validator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gsmithun4%2Fexpressjs-field-validator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gsmithun4","download_url":"https://codeload.github.com/gsmithun4/expressjs-field-validator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gsmithun4%2Fexpressjs-field-validator/sbom","scorecard":{"id":447263,"data":{"date":"2025-08-11","repo":{"name":"github.com/gsmithun4/expressjs-field-validator","commit":"779c9dce86b4826ca0c8f39b0cc08054cfc1d68d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.8,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/10 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/npmpublish.yml:1","Warn: no topLevel permission defined: .github/workflows/sonarqube.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":6,"reason":"dependency not pinned by hash detected -- score normalized to 6","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/npmpublish.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/gsmithun4/expressjs-field-validator/npmpublish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/npmpublish.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/gsmithun4/expressjs-field-validator/npmpublish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/sonarqube.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/gsmithun4/expressjs-field-validator/sonarqube.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/sonarqube.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/gsmithun4/expressjs-field-validator/sonarqube.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/sonarqube.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/gsmithun4/expressjs-field-validator/sonarqube.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/sonarqube.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/gsmithun4/expressjs-field-validator/sonarqube.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/sonarqube.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/gsmithun4/expressjs-field-validator/sonarqube.yml/master?enable=pin","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   3 out of   3 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 29 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"20 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-rv95-896h-c2vc","Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-8hfj-j24r-96c4","Warn: Project is vulnerable to: GHSA-wc69-rhjr-hc9g","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p","Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T07:08:03.674Z","repository_id":33971284,"created_at":"2025-08-19T07:08:03.674Z","updated_at":"2025-08-19T07:08:03.674Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30198469,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T19:07:06.838Z","status":"ssl_error","status_checked_at":"2026-03-06T18:57:34.882Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["data","express-js","expressjs","json-request","middleware","nodejs","request","rest-api","validation"],"created_at":"2025-09-01T08:01:49.623Z","updated_at":"2026-03-06T21:12:12.035Z","avatar_url":"https://github.com/gsmithun4.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# expressjs-field-validator\nRequest field validator for expressjs\n\n🛠️ **[Config Builder Tool](https://expressjs-field-validator-configs-builder.onrender.com)** - Generate validation configs visually!\n\n[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=gsmithun4_expressjs-field-validator\u0026metric=reliability_rating)](https://sonarcloud.io/dashboard?id=gsmithun4_expressjs-field-validator)\n[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=gsmithun4_expressjs-field-validator\u0026metric=bugs)](https://sonarcloud.io/dashboard?id=gsmithun4_expressjs-field-validator)\n[![code_smells](https://sonarcloud.io/api/project_badges/measure?project=gsmithun4_expressjs-field-validator\u0026metric=code_smells)](https://sonarcloud.io/dashboard?id=gsmithun4_expressjs-field-validator)\n[![coverage](https://sonarcloud.io/api/project_badges/measure?project=gsmithun4_expressjs-field-validator\u0026metric=coverage)](https://sonarcloud.io/dashboard?id=gsmithun4_expressjs-field-validator)\n[![duplicated_lines_density](https://sonarcloud.io/api/project_badges/measure?project=gsmithun4_expressjs-field-validator\u0026metric=duplicated_lines_density)](https://sonarcloud.io/dashboard?id=gsmithun4_expressjs-field-validator)\n[![ncloc](https://sonarcloud.io/api/project_badges/measure?project=gsmithun4_expressjs-field-validator\u0026metric=ncloc)](https://sonarcloud.io/dashboard?id=gsmithun4_expressjs-field-validator)\n[![sqale_rating](https://sonarcloud.io/api/project_badges/measure?project=gsmithun4_expressjs-field-validator\u0026metric=sqale_rating)](https://sonarcloud.io/dashboard?id=gsmithun4_expressjs-field-validator)\n[![alert_status](https://sonarcloud.io/api/project_badges/measure?project=gsmithun4_expressjs-field-validator\u0026metric=alert_status)](https://sonarcloud.io/dashboard?id=gsmithun4_expressjs-field-validator)\n[![security_rating](https://sonarcloud.io/api/project_badges/measure?project=gsmithun4_expressjs-field-validator\u0026metric=security_rating)](https://sonarcloud.io/dashboard?id=gsmithun4_expressjs-field-validator)\n[![security_rating](https://sonarcloud.io/api/project_badges/measure?project=gsmithun4_expressjs-field-validator\u0026metric=security_rating)](https://sonarcloud.io/dashboard?id=gsmithun4_expressjs-field-validator)\n[![sqale_index](https://sonarcloud.io/api/project_badges/measure?project=gsmithun4_expressjs-field-validator\u0026metric=sqale_index)](https://sonarcloud.io/dashboard?id=gsmithun4_expressjs-field-validator)\n[![vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=gsmithun4_expressjs-field-validator\u0026metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=gsmithun4_expressjs-field-validator)\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\u003c!-- **Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)* --\u003e\n\n- [Installation](#installation)\n- [How To Use](#how-to-use)\n- [Getting Started](#getting-started)\n  - [Defining a Field](#defining-a-field)\n    - [Available Options](#available-options)\n      - [isRequired()](#isrequired)\n      - [isArray()](#isarray)\n      - [isObject()](#isobject)\n      - [isNumber()](#isnumber)\n      - [isEmail()](#isemail)\n      - [isUUID()](#isuuid)\n      - [isBoolean()](#isboolean)\n      - [isDate()](#isdate)\n      - [dateFormat(format)](#dateformatformat)\n      - [minimumNumber(min)](#minimumnumbermin)\n      - [maximumNumber(max)](#maximumnumbermax)\n      - [minimumLength(min)](#minimumlengthmin)\n      - [maximumLength(max)](#maximumlengthmax)\n      - [shouldInclude(inclues)](#shouldincludeinclues)\n      - [shouldExclude(excludes)](#shouldexcludeexcludes)\n      - [isMobileNumberWithCountryCode(countryCode)](#ismobilenumberwithcountrycodecountrycode)\n      - [isMobileNumberWithCountryCodeMandatory()](#ismobilenumberwithcountrycodemandatory)\n      - [isMobileNumberWithMinimumLength(min)](#ismobilenumberwithminimumlengthmin)\n      - [isMobileNumberWithMaximumLength(max)](#ismobilenumberwithmaximumlengthmax)\n      - [addChild(child)](#addchildchild)\n      - [addChildren(children)](#addchildrenchildren)\n      - [sendErrorMessage(message)](#senderrormessagemessage)\n      - [convertToFormat(format)](#converttoformatformat)\n      - [defaultValue(value)](#defaultvaluevalue)\n      - [removeIfEmpty()](#removeifempty)\n  - [Creating a validation middleware](#creating-a-validation-middleware)\n    - [Available Options](#available-options-1)\n      - [isToBeRejected()](#istoberejected)\n      - [isToBeForwarded()](#istobeforwarded)\n        - [checkService](#checkservice)\n        - [skipService](#skipservice)\n      - [sendErrorCode(errorCode)](#senderrorcodeerrorcode)\n      - [debug(isDebugEnabled)](#debugisdebugenabled)\n      - [removeIfEmpty()](#removeifempty-1)\n      - [cleanUp()](#cleanup)\n      - [addParams(paramList)](#addparamsparamlist)\n- [Dealing with nested objects](#dealing-with-nested-objects)\n  - [Request body](#request-body)\n  - [Validation](#validation)\n- [API Documentation Generator](#api-documentation-generator)\n  - [Hosting API Documentation](#hosting-api-documentation)\n- [Migration Guide](#migration-guide)\n  - [Migrating from v3.x to v4.x](#migrating-from-v3x-to-v4x)\n    - [Breaking Changes](#breaking-changes)\n    - [New Features](#new-features)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n\n## Installation  \n```\n$ npm install expressjs-field-validator\n```\n\n## How To Use\n\n```js\n const { \n  validateBody,\n  validateParam,\n  validateQuery,\n  param,\n} = require('expressjs-field-validator');\n```\n```js\nrouter.post('/users/:id',\nvalidateParam().addParams([\n  param('id').isNumber()\n]),\nvalidateBody().addParams([\n  param('userId').isNumber()\n]),\nvalidateQuery().addParams([\n  param('userName').isRequired()\n]),\nvalidateHeader().addParams([\n  param('Authorization').isRequired()\n]),\n(req, res, next) =\u003e {\n\n  // Main Service Here\n\n});\n```\n## Getting Started\n### Defining a Field\nUse `param(\u003cfield Name\u003e)` to define a field.\n```js\nparam('userName').isRequired()\n```\nDefines a field `userName` which is mandatory.\n#### Available Options\n##### isRequired()\nField is mandatory\n##### isArray()\nExpects array\n##### isObject()\nExpects object\n##### isNumber()\nExpects number\n##### isEmail()\nExpects email\n##### isUUID()\nExpects UUID string\n##### isBoolean()\nExpects boolean value\n##### isDate()\nExpects a date with default format `YYYY-MM-DD`\n##### dateFormat(format)\n* `format` *Mandatory* String\nspecify date format, supported\n```\nYYYY-MM-DD\nDD-MM-YYYY\nMM-DD-YYYY\nYYYY/MM/DD\nDD/MM/YYYY\nMM/DD/YYYY\n```\n##### convertToFormat(format)\n* `format` *Mandatory* String\nConverts a validated date value to the specified format. Must be used with `isDate()`. The source format is determined by `dateFormat()` (defaults to `YYYY-MM-DD` if not set).\n\nSupported formats are the same as `dateFormat`:\n```\nYYYY-MM-DD\nDD-MM-YYYY\nMM-DD-YYYY\nYYYY/MM/DD\nDD/MM/YYYY\nMM/DD/YYYY\n```\n\nIf the specified format is not in the supported list, the conversion is silently skipped and the original value is preserved.\n\n```js\n// Convert DD/MM/YYYY input to YYYY-MM-DD\nparam('birthDate').isDate().dateFormat('DD/MM/YYYY').convertToFormat('YYYY-MM-DD')\n// Input: \"25/12/2024\" → Value after validation: \"2024-12-25\"\n\n// Convert with default source format (YYYY-MM-DD) to DD-MM-YYYY\nparam('eventDate').isDate().convertToFormat('DD-MM-YYYY')\n// Input: \"2024-12-25\" → Value after validation: \"25-12-2024\"\n```\n##### minimumNumber(min)\n* `min` *Mandatory* Number\nExpects number and must be greater than or equal to `min`\n##### maximumNumber(max)\n* `max` *Mandatory* Number\nExpects number and must be less than or equal to `max`\n##### minimumLength(min)\n* `min` *Mandatory* Number\nExpects number/string and length must be less than or equal to `min`\n##### maximumLength(max)\n* `max` *Mandatory* Number\nExpects number/string and length must be less than or equal to `max`\n##### shouldInclude(inclues)\n* `inclues` *Mandatory* Array\nExpects number/string and must be one of given array `includes`\n##### shouldExclude(excludes)\n* `excludes` *Mandatory* Array\nExpects number/string and must not be one of given array `excludes`\n##### isMobileNumberWithCountryCode(countryCode)\n* `countryCode` *Mandatory* String\nExpects mobile number with or without `countryCode`\n##### isMobileNumberWithCountryCodeMandatory()\nExpects mobile number which should starts with the country code set with `isMobileNumberWithCountryCode`\n##### isMobileNumberWithMinimumLength(min)\n* `min` *Mandatory* Number\nMinimum length of mobile number without country code\n##### isMobileNumberWithMaximumLength(max)\n* `max` *Mandatory* Number\nMaximum length of mobile number without country code\n##### customValidator(function)\n* `function` *Mandatory* Function\nA function with arguments (`value`, `req`, `error`)\n`value` is the value of the field\n`req` request object\n`error` function with takes error message, should be called on error\n```js\n(value, req, error) =\u003e {\n  if (value !== 100) {\n    error('Invalid value customValidator');\n  }\n}\n```\n##### addChild(child)\n* `child` *Mandatory* field definition object\nAdd a child object for arrays and objects\n##### addChildren(children)\n* `children` *Mandatory* Array of field definition objects\nAdd a list of children objects for arrays and objects\n##### sendErrorMessage(message)\n* `message` *Mandatory* String\nCustom message to be send back in case of validation failure\n```js\n// Default message\n{\n    \"error\": [\n        {\n            \"location\": \"body.sort\",\n            \"param\": \"sort\",\n            \"message\": \"Invalid Field Error\"\n        }\n    ]\n}\n// Custom message\n{\n    \"error\": [\n        {\n            \"location\": \"body.sort\",\n            \"param\": \"sort\",\n            \"message\": \"\u003cYour Custom Error Message\u003e\"\n        }\n    ]\n}\n```\n##### defaultValue(value)\n* `value` *Mandatory* Any value (non-array, non-object)\nSets a default value for the field when the current value is `undefined`, `null`, or `''` (empty string). Only applies to fields that are not arrays or objects.\n```js\nparam('status').defaultValue('active')\nparam('count').isNumber().defaultValue(0)\n```\n##### removeIfEmpty()\nRemoves the field key from the request if the value is considered empty.\n* For arrays: removes if `[]`\n* For objects: removes if `{}`\n* For other fields: removes if `undefined`, `null`, or `''`\n```js\nparam('status').removeIfEmpty()\nparam('items').isArray().removeIfEmpty()\nparam('meta').isObject().removeIfEmpty()\n```\n\u003e **Note:** When both `defaultValue` and `removeIfEmpty` are used together, `defaultValue` is applied first. If the default value is non-empty, the field is kept.\n```js\nparam('status').defaultValue('active').removeIfEmpty() // field is kept with value 'active'\n```\n### Creating a validation middleware\n* `validateBody()` *Validate body*\n* `validateParam()` *Validate param*\n* `validateQuery()` *Validate query*\n* `validateHeader()` *Validate header*\n\n#### Available Options\n##### isToBeRejected()\nDefines the validation failure event - Server returns http status code set via `sendErrorCode` (default 422), :heavy_exclamation_mark: will not proceed to the next middleware\nResponse body\n```js\n{\n    \"error\": [\n        {\n            \"location\": \"body.sort\",\n            \"param\": \"sort\",\n            \"message\": \"Invalid Field Error\"\n        }\n    ]\n}\n```\n##### isToBeForwarded()\nDefines the validation failure event - Error is set to `request.locals.data` and error code to `request.locals.statusCode`, :white_check_mark: will proceed to the next middleware\nError object\nResponse body\n```js\n{\n    \"error\": [\n        {\n            \"location\": \"body.sort\",\n            \"param\": \"sort\",\n            \"message\": \"Invalid Field Error\"\n        }\n    ]\n}\n```\n###### checkService\n```js\n  const { checkService } = require('expressjs-field-validator');\n```\nPass middleware to `checkService`, which must be skipped if `isToBeForwarded` enabled and validation errors are found\n```js\nrouter.get('/users/:id',\nvalidateBody().isToBeForwarded().sendErrorCode(500).debug(false).addParams([\n  param('id').isRequired().isNumber()\n]),\ncheckService((req, res, next) =\u003e {\n\n  // This middleware is skipped if id is empty or not a number\n  \n}),\n(req, res, next) =\u003e {\n\n  // This middleware Will not be skipped, error data will be availble here - req.locals.data and status code - request.locals.statusCode here \n  \n});\n```\n###### skipService\nmanually invoke forward mode, if this is set from any middleware, the middlewares wrapped inside `checkService` won't be executed\n```js\n const { skipService } = require('expressjs-field-validator');\n```\n```js\nrouter.get('/users/:id',\n(req, res, next) =\u003e {\n\n  skipService(req, 'SOME-ERROR');\n  next();\n  \n}),\n \ncheckService((req, res, next) =\u003e {\n\n  // This middleware is skipped\n  \n}),\n(req, res, next) =\u003e {\n\n  // This middleware Will not be skipped, error data will be availble here - req.locals.data and status code - request.locals.statusCode here \n  \n});\n```\n##### sendErrorCode(errorCode)\n* `errorCode` *Mandatory* Error code which should be rejected\n##### debug(isDebugEnabled)\n* `isDebugEnabled` *Mandatory* Pass `true` for development environments, the error object will contain more details about error\nError object\n```js\n{\n    \"error\": [\n        {\n            \"location\": \"body.sort\",\n            \"param\": \"sort\",\n            \"message\": \"Invalid Field Error :: somevalueforsort Must Be A Boolean\" // More details on error\n        }\n    ]\n}\n```\n##### removeIfEmpty()\nApplies `removeIfEmpty` behavior to all fields in the validation middleware. When enabled:\n* Arrays: removed if `[]`\n* Objects: removed if `{}`\n* Other fields: removed if `undefined`, `null`, or `''`\n\nThis is a convenience method to avoid adding `removeIfEmpty()` to each field individually.\n```js\n// Instead of adding removeIfEmpty() to each field:\nvalidateBody().addParams([\n  param('name').removeIfEmpty(),\n  param('email').removeIfEmpty(),\n  param('phone').removeIfEmpty(),\n])\n\n// You can add it once at the top level:\nvalidateBody().removeIfEmpty().addParams([\n  param('name'),\n  param('email'),\n  param('phone'),\n])\n```\n\u003e **Note:** Field-level `removeIfEmpty()` can still be used when you only want to remove specific fields.\n##### cleanUp()\nRemoves any keys from the request that are not declared in the validation params. This sanitizes the input to only include explicitly defined fields. Works recursively on nested objects and arrays.\n```js\n// Request body: { name: \"John\", email: \"john@test.com\", hackAttempt: \"malicious\", extra: \"data\" }\nvalidateBody().cleanUp().addParams([\n  param('name').isRequired(),\n  param('email').isEmail(),\n])\n// After validation, req.body will only contain: { name: \"John\", email: \"john@test.com\" }\n// The \"hackAttempt\" and \"extra\" keys are removed\n```\nThis is useful for:\n* Security: Preventing unexpected fields from being processed\n* Data sanitization: Ensuring only declared fields reach your business logic\n* API consistency: Keeping request payloads clean\n\n\u003e **Note:** `cleanUp()` also works recursively on nested objects and arrays defined with `addChild()` or `addChildren()`.\n##### addParams(paramList)\n* `paramList` *Mandatory* Array of field definition objects\n```js\nvalidateBody().addParams([\n  // Add List of definition here\n  param('field1').isRequired(),\n])\n```\nDefinintion of a field here : [Defining a Field](#defining-a-field)\n## Dealing with nested objects\n### Request body\n```js\n{\n  \"field1\": \"Value\", // String, Mandatory\n  \"field2\": [ // array, Mandatory\n    { \"field21\": \"44443\" }, // object Optional, number mandatory\n    { \"field21\": \"44443\" }\n  ],\n  \"field3\": { // Object Optional\n    \"field31\": \"true\", // Boolean Mandatory\n    \"field32\": \"String\" // String Mandatory\n  },\n  \"field4\": [ // array, Mandatory\n    123, 445, 3434 // Number Optional\n  ],\n}\n```\nShould send http status code 500 in case of error\n### Validation\n```js\nrouter.post('/users/:id',\nvalidateBody().isToBeRejected().sendErrorCode(500).addParams([\n  param('field1').isRequired(),\n  param('field2').isRequired().isArray().isRequired().addChild(\n    param('field2-array').isObject().addChild( // field2-array is for tracking, you can give any name here\n      param('field21').isNumber().isRequired()\n    )\n  ),\n  param('field3').isObject().addChildren([\n    param('field31').isBoolean().isRequired(),\n    param('field32').isRequired()\n  ]),\n  param('field4').isRequired().isArray().isRequired().addChild(\n    param('field4-array').isNumber()\n  ),\n]),\nvalidateParam().isToBeRejected().sendErrorCode(500).addParams([\n  param('field1').isRequired(),\n]),\n// define validateQuery(), \n// define validateHeader(),\n(req, res, next) =\u003e {\n\n  // Main Service Here\n\n});\n```\n\n## API Documentation Generator\n\nAutomatically generate beautiful HTML documentation for your API endpoints. The generator extracts all routes with validation middlewares and creates an interactive documentation page.\n\n### Usage\n\n```js\nconst express = require('express');\nconst { \n  validateBody, \n  validateQuery, \n  param, \n  generateDocs \n} = require('expressjs-field-validator');\n\nconst app = express();\n\n// Define your routes with validation\napp.post('/users',\n  validateBody().isToBeRejected().addParams([\n    param('name').isRequired(),\n    param('email').isRequired().isEmail(),\n  ]),\n  (req, res) =\u003e res.status(201).send({ message: 'User created' })\n);\n\napp.get('/users/:id',\n  validateQuery().isToBeRejected().addParams([\n    param('include').shouldInclude(['profile', 'settings', 'posts']),\n  ]),\n  (req, res) =\u003e res.send({ user: {} })\n);\n\n// Generate documentation AFTER all routes are registered\ngenerateDocs(app, {\n  title: 'My API',\n  version: '1.0.0',\n  outputDir: './docs',\n  filename: 'api-docs.html'\n});\n\napp.listen(3000);\n```\n\n### Options\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `outputDir` | `string` | `'./docs'` | Output directory for the generated HTML file |\n| `filename` | `string` | `'api-docs.html'` | Output filename |\n| `title` | `string` | `'API Documentation'` | Documentation title |\n| `version` | `string` | - | API version to display |\n\n### Features\n\n- 🎨 **Beautiful dark theme** with syntax highlighting\n- 🔍 **Search functionality** to filter endpoints\n- 📊 **Statistics** showing endpoint counts by method\n- 📋 **Detailed field information** including types, constraints, and nesting\n- 📝 **Sample request body** with copy-to-clipboard functionality\n- 🎯 **Response config display** (mode, error codes, cleanUp, etc.)\n- 📱 **Responsive design** for mobile viewing\n\n### Hosting API Documentation\n\nYou can serve the generated HTML documentation using Express static middleware:\n\n```js\nconst express = require('express');\nconst path = require('path');\nconst { generateDocs, validateBody, param } = require('expressjs-field-validator');\n\nconst app = express();\napp.use(express.json());\n\n// Define your API routes\napp.post('/users',\n  validateBody().isToBeRejected().addParams([\n    param('name').isRequired(),\n    param('email').isRequired().isEmail(),\n  ]),\n  (req, res) =\u003e res.status(201).send({ message: 'User created' })\n);\n\n// Generate documentation\ngenerateDocs(app, {\n  title: 'My API',\n  version: '1.0.0',\n  outputDir: './docs'\n});\n\n// Serve the documentation at /api-docs\napp.use('/api-docs', express.static(path.join(__dirname, 'docs')));\n\napp.listen(3000, () =\u003e {\n  console.log('Server running on http://localhost:3000');\n  console.log('API Docs available at http://localhost:3000/api-docs/api-docs.html');\n});\n```\n\n**Alternative: Serve docs at root path**\n\n```js\n// Serve docs at /docs endpoint\napp.use('/docs', express.static(path.join(__dirname, 'docs')));\n\n// Or redirect /docs to the HTML file directly\napp.get('/docs', (req, res) =\u003e {\n  res.sendFile(path.join(__dirname, 'docs', 'api-docs.html'));\n});\n```\n\n**Production Tips:**\n- Add caching headers for better performance\n- Use environment variables to conditionally enable docs (disable in production if needed)\n- Consider adding authentication to protect internal API documentation\n\n```js\n// Only serve docs in non-production\nif (process.env.NODE_ENV !== 'production') {\n  app.use('/api-docs', express.static(path.join(__dirname, 'docs')));\n}\n```\n\n## Migration Guide\n\n### Migrating from v3.x to v4.x\n\n#### Breaking Changes\n\n##### 1. `end()` removed from field definitions\n\n`end()` is no longer required (or available) when defining fields with `param()`.\n\n```diff\n- param('userName').isRequired().end()\n+ param('userName').isRequired()\n```\n\n```diff\n- param('field21').isNumber().isRequired().end()\n+ param('field21').isNumber().isRequired()\n```\n\n##### 2. `done()` removed from validation middleware\n\n`done()` is no longer required (or available) when creating validation middleware.\n\n```diff\n- validateBody().addParams([\n-   param('field1').isRequired().end(),\n- ]).done()\n+ validateBody().addParams([\n+   param('field1').isRequired(),\n+ ])\n```\n\n```diff\n- validateParam().isToBeRejected().sendErrorCode(500).addParams([\n-   param('id').isNumber().end(),\n- ]).done()\n+ validateParam().isToBeRejected().sendErrorCode(500).addParams([\n+   param('id').isNumber(),\n+ ])\n```\n\n##### Full Before / After Example\n\n**v3.x**\n```js\nrouter.post('/users/:id',\nvalidateParam().addParams([\n  param('id').isNumber().end()\n]).done(),\nvalidateBody().isToBeRejected().sendErrorCode(500).addParams([\n  param('name').isRequired().end(),\n  param('email').isEmail().end(),\n  param('role').shouldInclude(['admin', 'user']).end(),\n]).done(),\n(req, res, next) =\u003e {\n  // Main Service\n});\n```\n\n**v4.x**\n```js\nrouter.post('/users/:id',\nvalidateParam().addParams([\n  param('id').isNumber()\n]),\nvalidateBody().isToBeRejected().sendErrorCode(500).addParams([\n  param('name').isRequired(),\n  param('email').isEmail(),\n  param('role').shouldInclude(['admin', 'user']),\n]),\n(req, res, next) =\u003e {\n  // Main Service\n});\n```\n\n#### New Features\n\nThe following features are new in v4.x:\n\n##### `defaultValue(value)`\nSets a default value for a field when the value is `undefined`, `null`, or `''`.\n```js\nparam('status').defaultValue('active')\nparam('count').isNumber().defaultValue(0)\n```\n\n##### `removeIfEmpty()`\nRemoves the field key from the request if the value is empty.\n```js\nparam('notes').removeIfEmpty()\nparam('tags').isArray().removeIfEmpty()\n```\n\n##### `convertToFormat(format)`\nConverts a validated date to a different format. The original value in the request is replaced with the converted value.\n```js\nparam('birthDate').isDate().dateFormat('DD/MM/YYYY').convertToFormat('YYYY-MM-DD')\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgsmithun4%2Fexpressjs-field-validator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgsmithun4%2Fexpressjs-field-validator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgsmithun4%2Fexpressjs-field-validator/lists"}