{"id":21283231,"url":"https://github.com/jpbaking/middleware-chainer","last_synced_at":"2026-05-21T07:46:04.492Z","repository":{"id":57296795,"uuid":"141784995","full_name":"jpbaking/middleware-chainer","owner":"jpbaking","description":"middleware-chainer","archived":false,"fork":false,"pushed_at":"2018-07-21T21:53:43.000Z","size":91,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-22T06:02:56.443Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/jpbaking.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-21T05:48:35.000Z","updated_at":"2018-09-26T11:43:10.000Z","dependencies_parsed_at":"2022-09-02T07:40:17.750Z","dependency_job_id":null,"html_url":"https://github.com/jpbaking/middleware-chainer","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpbaking%2Fmiddleware-chainer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpbaking%2Fmiddleware-chainer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpbaking%2Fmiddleware-chainer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jpbaking%2Fmiddleware-chainer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jpbaking","download_url":"https://codeload.github.com/jpbaking/middleware-chainer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243746131,"owners_count":20341203,"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":[],"created_at":"2024-11-21T11:07:32.080Z","updated_at":"2026-05-21T07:46:02.418Z","avatar_url":"https://github.com/jpbaking.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# middleware-chainer-1.0.0\n\nSimplifies Node.js [express](https://expressjs.com/) [middlewares](https://expressjs.com/en/guide/using-middleware.html) modularization.\n\nBest for those currently stuck with [swagger-node](https://www.npmjs.com/package/swagger) or alike; those that have limited means of middleware \"chaining\".\n\nBasically behaves similarly to [express](https://expressjs.com/) [middlewares](https://expressjs.com/en/guide/using-middleware.html) (including error handling).\n\nMake your code much more readable!\n\u003cbr /\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;_... and small enough to ease unit-testing!_\n\n### Contents:\n1. How-To?\n    1. \u003ca href=\"#basic\"\u003eBasic Usage\u003c/a\u003e\n        1. \u003ca href=\"#arguments\"\u003eBasic Arguments/Parameters\u003c/a\u003e\n    1. \u003ca href=\"#simple\"\u003eSimple Usage\u003c/a\u003e\n    1. \u003ca href=\"#factory\"\u003eFactory Usage\u003c/a\u003e\n        1. \u003ca href=\"#factory-arguments\"\u003eFactory Arguments/Parameters\u003c/a\u003e\n1. \u003ca href=\"#principles\"\u003ePrinciples/Inspiration\u003c/a\u003e\n1. \u003ca href=\"#coverage\"\u003e100% Code Coverage\u003c/a\u003e\n1. \u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\n\n## \u003ca name=\"basic\" /\u003eBasic Usage : `require('middleware-chainer')`\n\nHere we have a simple authentication API endpoints:\n\n```yaml\n# ---------------------------------------------\n# $BASEDIR/api/swagger/swagger.yaml\n# ---------------------------------------------\npaths:\n  /auth:\n    x-swagger-router-controller: auth\n    post:\n      operationId: login\n      description: User Authentication/Authorization (Generate Token)\n      # ...\n    delete:\n      operationId: logout\n      description: Invalidate User Token/s\n      # ...\n```\n\nHere's the controller:\n\n```javascript\n/**\n * $BASEDIR/api/controllers/auth.js\n */\nconst chain = require('middleware-chainer');\n\nconst loginHitCounter = require('./auth/login-hit-counter');\nconst loginErrorHandler = require('./auth/login-error-handler');\n\nconst login = require('./auth/login');\nconst logout = require('./auth/logout');\n\nmodule.exports = {\n  login: chain({ middlewares: [loginHitCounter, login, loginErrorHandler] }),\n  logout: logout\n};\n```\n\nIn the example above, `login` has a \"special 'pre' step (middleware)\" prior to actual `login`, plus a special error handler.\n\nHere's the would-be structure of the sample modularized [swagger-generated](https://www.npmjs.com/package/swagger) project above:\n\n```\n/swagger-project\n|-- /controllers\n|   |-- /auth\n|   |   |-- login.js\n|   |   |-- login.spec.js\n|   |   |-- login-error-handler.js\n|   |   |-- login-error-handler.spec.js\n|   |   |-- login-hit-counter.js\n|   |   |-- login-hit-counter.spec.js\n|   |   |-- logout.js\n|   |   |-- logout.spec.js\n|   |-- auth.js\n|   |-- auth.spec.js\n|-- /swagger\n|   |-- swagger.yaml\n```\n\n**Note:** `*.spec.js` being unit tests.\n\n### \u003ca name=\"arguments\" /\u003eThe `chain` Arguments\n\n`chain`, pertaining to the variable where `require('middleware-chainer')` was assigned in the example above.\n\nThe `chain` function takes a single object literal `{}` as argument. Keys are as follows:\n\n| Key | Type/Format | Description | Default | Example |\n| --- | ----------- | ----------- | ------- | ------- |\n| `name` | string | middleware name; shows in \"debug\" | `'mw-chain'` | `'lol'` |\n| `loggers` | object literal (ie: `{}`) | see next two entries (`loggers.*`) | - | - |\n| `loggers.debug` | function | receives \"message\" string as argument | `() =\u003e undefined` | `console.log` |\n| `loggers.error` | function | receives \"message\" string as argument | `console.error` | `console.log` |\n| `middlewares` | array of functions | array of middlewares `(req, res[, next])` or `(err, req, res, next)` | - | - |\n\nSample \"full\" configuration:\n\n```javascript\nconst debug = require('debug'); // https://www.npmjs.com/package/debug\nconst chain = require('middleware-chainer');\n\nconst chainedMiddleware = chain({\n  name: 'lol',\n  loggers: {\n    debug: debug,\n    error: debug\n  },\n  middlewares: [...]\n});\n```\n\nSample output from one of the unit tests with configured `loggers.debug` w/ `console.log`:\n\n![loggers.png](./.readme/loggers.png)\n\n**Hint**: Given the `loggers.error` has a default (`console.error`); you may opt to \"mute\" it by setting the value to: `() =\u003e undefined`.\n\n## \u003ca name=\"simple\" /\u003eSimple Usage : `require('middleware-chainer/simple')`\n\n```javascript\n/**\n * $BASEDIR/api/controllers/auth.js\n */\nconst chain = require('middleware-chainer/simple');\n\nconst loginHitCounter = require('./auth/login-hit-counter');\nconst loginErrorHandler = require('./auth/login-error-handler');\n\nconst login = require('./auth/login');\nconst logout = require('./auth/logout');\n\nmodule.exports = {\n  login: chain(loginHitCounter, login, loginErrorHandler),\n  logout: logout\n};\n```\n\nNo fuss. **Simple... Just middlewares**.\n\n## \u003ca name=\"factory\" /\u003eFactory Usage : `require('middleware-chainer/factory')`\n\n```javascript\n/**\n * $BASEDIR/api/controllers/auth.js\n */\nconst ChainFactory = require('middleware-chainer/factory');\n\nconst loginHitCounter = require('./auth/login-hit-counter');\nconst loginErrorHandler = require('./auth/login-error-handler');\n\nconst loginChain = new ChainFactory({ // or `ChainFactory({})`\n  name: 'login-chain',\n  loggers: { debug: console.log },\n  before: [loginHitCounter],\n  after: [loginErrorHandler]\n});\n\nconst login = require('./auth/login');\nconst refresh = require('./auth/refresh-token');\nconst logout = require('./auth/logout');\n\nmodule.exports = {\n  login: loginChain(login), // chain(loginHitCounter, login, loginErrorHandler)\n  refresh: loginChain(refresh), // chain(loginHitCounter, refresh, loginErrorHandler)\n  logout: logout\n};\n```\n\n\u003ca name=\"factory-arguments\" /\u003eConstructor arguments are very much the same as the \"basic\", apart from one omission and two additions:\n\n| Key | Type/Format | Description | Default | Example |\n| --- | ----------- | ----------- | ------- | ------- |\n| ~~`middlewares`~~ | ~~array of functions~~ | ~~array of middlewares `(req, res[, next])` or `(err, req, res, next)`~~ | - | - |\n| `before` | array of functions | middlewares to be put at the **beggining** of the \"chain\" | - | - |\n| `after` | array of functions | middlewares to be put at the **end** of the \"chain\" | - | - |\n\n## \u003ca name=\"principles\" /\u003ePrinciples/Inspiration\n\nAs described in this Wikipedia [page](https://en.wikipedia.org/wiki/Unit_testing#Description), UNIT TESTING is described: \"Intuitively, one can view a unit as the smallest testable part of an application\". Therefore, being able to break-apart your application into smallest possible (sensible) modules is BEST!\n\nIf you employ/enforce the ideals of \"single responsibility\" per-class/file/module; [`middleware-chainer`](https://www.npmjs.com/package/middleware-chainer) is an easy go-to.\n\n## \u003ca name=\"coverage\" /\u003e100% Code Coverage\n\nSee for yourself!\n\n1. Clone:\n    ```bash\n    git clone https://github.com/jpbaking/middleware-chainer.git\n    ```\n1. ...of course go into folder:\n    ```bash\n    cd middleware-chainer\n    ```\n1. Download/install dependencies:\n    ```bash\n    npm install\n    ```\n1. Test!!!\n    ```bash\n    npm test\n    ```\n1. Expected output:\n\u003cbr /\u003e![coverage.png](./.readme/coverage.png)\n\n## \u003ca name=\"license\" /\u003eLicense\n\n### MIT License\n\n#### Copyright (c) 2018 Joseph Baking\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\n**THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjpbaking%2Fmiddleware-chainer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjpbaking%2Fmiddleware-chainer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjpbaking%2Fmiddleware-chainer/lists"}