{"id":15638723,"url":"https://github.com/lirantal/express-version-route","last_synced_at":"2025-04-09T15:04:48.878Z","repository":{"id":44709174,"uuid":"91352809","full_name":"lirantal/express-version-route","owner":"lirantal","description":"A Node.js express middleware that implements API versioning for route controllers","archived":false,"fork":false,"pushed_at":"2023-06-20T17:06:57.000Z","size":2162,"stargazers_count":91,"open_issues_count":4,"forks_count":10,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-09T15:04:42.484Z","etag":null,"topics":["api","api-versioning","expessjs","expressjs-middleware","nodejs"],"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/lirantal.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2017-05-15T15:19:34.000Z","updated_at":"2024-08-20T18:28:52.000Z","dependencies_parsed_at":"2024-04-16T11:52:52.190Z","dependency_job_id":"4aa1b684-64e3-45a0-98e5-957c1f98ffc7","html_url":"https://github.com/lirantal/express-version-route","commit_stats":{"total_commits":53,"total_committers":10,"mean_commits":5.3,"dds":0.4339622641509434,"last_synced_commit":"d0a9a15eda31f0079b3bda078d42c2d60ae551e7"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lirantal%2Fexpress-version-route","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lirantal%2Fexpress-version-route/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lirantal%2Fexpress-version-route/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lirantal%2Fexpress-version-route/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lirantal","download_url":"https://codeload.github.com/lirantal/express-version-route/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248055284,"owners_count":21040157,"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":["api","api-versioning","expessjs","expressjs-middleware","nodejs"],"created_at":"2024-10-03T11:22:52.278Z","updated_at":"2025-04-09T15:04:48.860Z","avatar_url":"https://github.com/lirantal.png","language":"JavaScript","readme":"# express-version-route\n\n[![view on npm](http://img.shields.io/npm/v/express-version-route.svg)](https://www.npmjs.org/package/express-version-route)\n[![view on npm](http://img.shields.io/npm/l/express-version-route.svg)](https://www.npmjs.org/package/express-version-route)\n[![Build](https://github.com/lirantal/express-version-route/workflows/CI/badge.svg?branch=master\u0026event=push)](https://github.com/lirantal/express-version-route/actions?query=workflow%3ACI)\n[![Codecov](https://img.shields.io/codecov/c/gh/lirantal/express-version-route.svg)](https://codecov.io/gh/lirantal/express-version-route)\n[![npm module downloads](http://img.shields.io/npm/dt/express-version-route.svg)](https://www.npmjs.org/package/express-version-route)\n[![Known Vulnerabilities](https://snyk.io/test/github/lirantal/express-version-route/badge.svg)](https://snyk.io/test/github/lirantal/express-version-route)\n[![Security Responsible Disclosure](https://img.shields.io/badge/Security-Responsible%20Disclosure-yellow.svg)](https://github.com/nodejs/security-wg/blob/master/processes/responsible_disclosure_template.md\n)\n\n[![express-version-route](https://snyk.io/advisor/npm-package/express-version-route/badge.svg)](https://snyk.io/advisor/npm-package/express-version-route)\n\nThis npm package provides an Express middleware to load route controllers based on api versions.\n\nImplementing API Versioning as simple as:\n\n![](.github/express-version-route.png)\n\nnow any request would be handled with the appropriate route handler in accordance to `request.version`.\n\n## Usage\n\nCreate a map where the key is the version of the supported controller, and the value is a regular Express route function signature.\n\n```js\nconst versionRouter = require('express-version-route')\n\nconst routesMap = new Map()\nroutesMap.set('1.0', (req, res, next) =\u003e {\n  return res.status(200).json({'message': 'hello to you version 1.0'})\n})\n```\n\nThen, on the route which you wish to version, call the `route` function of this module with the map you created:\n\n```js\nrouter.get('/test', versionRouter.route(routesMap))\n```\n\nIf no route matches the version requested by a client then the next middleware in the chain will be called.\nTo set a route fallback incase no version matches set a 'default' key on the routes map, for example:\n\n```js\nroutesMap.set('default', (req, res, next) =\u003e {\n  return res.status(200).json({'message': 'hello to you, this is the default route'})\n})\n``` \n\nIf maximal possible version (for example to get the latest bugfix) is necessary, then please specify `useMaxVersion: true` in `route` function, then the maximal possible version will be returned for your request. For example for `1.0` request, the version `1.0.2` will be returned:\n\n```js\nconst routesMap = new Map()\nroutesMap.set('1.0.0', (req, res, next) =\u003e {\n  return res.status(200).json({'message': 'hello to you version 1.0.0'})\n})\nroutesMap.set('1.0.2', (req, res, next) =\u003e {\n  return res.status(200).json({'message': 'hello to you version 1.0.2'})\n})\n\nrouter.get('/test', versionRouter.route(routesMap,{useMaxVersion: true}))\n```\n\n\n## Usage with TypeScript\n\n```ts\nimport * as versionRouter from 'express-version-route'\nimport { Router, Handler } from 'express';\n\nconst router = Router();\nconst routesMap = new Map\u003cstring, Handler\u003e();\n\nroutesMap.set('1.0', (req, res, next) =\u003e {\n  return res.status(200).json({'message': 'hello to you version 1.0'})\n})\n\nroutesMap.set('default', (req, res, next) =\u003e {\n  return res.status(200).json({'message': 'hello to you, this is the default route'})\n})\n\nrouter.get('/test', versionRouter.route(routesMap))\n```\n\n## How it works\n\n### The Library\n\nA requested version from the client must be available on the request object at `req.version`.\nYou are encouraged to use this module's twin: [express-version-request](https://github.com/lirantal/express-version-request) which is another simple Express middleware that populates `req.version` from the client's X-Api-Version header, Accept header or from a query string (such as 'api-version=1.0.0')\n\nThe key for the routes versions you define can be a non-semver format, for example: `1.0` or just `1`. Under the hood, `expression-version-route` uses the `semver` module to check if the version found on the request object at `req.version` matches the route. \n\n### Client-Server flow\n\n1. An API client will send a request to your API endpoint with an HTTP header that specifies the requested version of the API to use: \n```bash\ncurl --header \"X-Api-Version: 1.0.0\" https://www.example.com/api/users\n```\n\n2. The `express-version-request` library will parse the `X-Api-Version` and sets Express's `req.version` property to 1.0.0.\n3. The `express-version-route` library, when implemented like the usage example above will match the 1.0 route version because semver will match 1.0.0 to 1.0, and then reply with the JSON payload `{'message': 'hello to you version 1.0'}`.  \n\n\n## Installation\n\n```bash\nyarn add express-version-route\n```\n\n## TypeScript Support\n\n```bash\nyarn add --dev @types/express-version-route\n```\n\n_Note: Don't forget to add types for Express as well!_\n\n## Tests\n\n```bash\nyarn test\n```\n\nProject linting:\n\n```bash\nyarn lint\n```\n\n## Coverage\n\n```bash\nyarn test:coverage\n```\n\n## Commit\n\nThe project uses the commitizen tool for standardizing changelog style commit\nmessages so you should follow it as so:\n\n```bash\ngit add .           # add files to staging\nyarn commit      # use the wizard for the commit message\n```\n\n## On API Versioning...\n\nAn API versioning is a practice that enables services to evolve their APIs with new changes, signatures and the overall API contract without interrupting API consumers and forcing them to repeatedly make changes in order to keep in pace with changes to APIs.\n\nSeveral methodologies exist to version your API:\n* URL: A request specifies the version for the resource: `http://api.domain.com/api/v1/schools/3/students`\n* Query String: A request specifies the resource in a query string: `http://api.domain.com/api/schools/3/students?api-version=1`\n* Custom HTTP Header: A request to a resource `http://api.domain.com/api/schools/3/students` with a custom HTTP header set in the request `X-Api-Version: 1`\n* MIME Type content negotiation: A request to a resource `http://api.domain.com/api/schools/3/students` with an `Accept` header that specifies the requested content and its version: `Accept: application/vnd.ecma.app-v2+json`\n\nThere is no strict rule on which methodology to follow and each has their own pros and cons. The RESTful approach is the semantic mime-type content negotiation, but a more pragmatic solution is the URL or custom HTTP header.\n\n### Why API Versioning at all ?\n\nUpgrading APIs with some breaking change would lead to breaking existing products, services or even your own frontend web application which is dependent on your API contract. By implementing API versioning you can ensure that changes you make to your underlying API endpoints are not affecting systems that consume them, and using a new version of an API is an opt-in on the consumer. [read more...](https://apigee.com/about/blog/technology/restful-api-design-tips-versioning)\n\n## Alternative Node.js libraries\n\nSeveral npm projects exist which provide similar API versioning capabilities to Express projects, and I have even contributed Pull Requests to some of them that provide fixes or extra functionality but unfortunately they all seem to be unmaintained, or buggy.\n\n* https://github.com/Prasanna-sr/express-routes-versioning\n* https://github.com/elliotttf/express-versioned-routes\n* https://github.com/biowink/express-route-versioning\n\n## Author\n\nLiran Tal \u003cliran.tal@gmail.com\u003e\n","funding_links":[],"categories":["Projects by main language"],"sub_categories":["Old Projects"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flirantal%2Fexpress-version-route","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flirantal%2Fexpress-version-route","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flirantal%2Fexpress-version-route/lists"}