{"id":13423803,"url":"https://github.com/piglovesyou/flow-middleware","last_synced_at":"2025-03-16T10:32:31.403Z","repository":{"id":43334337,"uuid":"244638044","full_name":"piglovesyou/flow-middleware","owner":"piglovesyou","description":"Run Express middlewares anywhere🚀","archived":false,"fork":false,"pushed_at":"2025-03-13T07:40:58.000Z","size":71,"stargazers_count":16,"open_issues_count":7,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-13T08:32:30.963Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/piglovesyou.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-03T13:05:13.000Z","updated_at":"2022-01-26T00:04:15.000Z","dependencies_parsed_at":"2022-09-17T13:51:06.634Z","dependency_job_id":"e76ed61e-4695-4487-afb6-362a7fc82518","html_url":"https://github.com/piglovesyou/flow-middleware","commit_stats":null,"previous_names":["piglovesyou/compose-middleware"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piglovesyou%2Fflow-middleware","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piglovesyou%2Fflow-middleware/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piglovesyou%2Fflow-middleware/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piglovesyou%2Fflow-middleware/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/piglovesyou","download_url":"https://codeload.github.com/piglovesyou/flow-middleware/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243814907,"owners_count":20352037,"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-07-31T00:00:42.887Z","updated_at":"2025-03-16T10:32:31.103Z","avatar_url":"https://github.com/piglovesyou.png","language":"TypeScript","readme":"# flow-middleware ![Node CI](https://github.com/piglovesyou/flow-middleware/actions/workflows/nodejs.yml/badge.svg) [![npm version](https://badge.fury.io/js/flow-middleware.svg)](https://badge.fury.io/js/flow-middleware)\n\nRun Express middlewares on any Node.js server framework without hacking/polluting native `req`/`res` objects with Proxy.\n\n[Checkout the Next.js example](https://github.com/piglovesyou/nextjs-passport-oauth-example) with [Passport.js](http://www.passportjs.org/) integration.\n\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003eWhy, How\u003c/b\u003e\u003c/summary\u003e\n\u003cp\u003e\n    \n# Why\n\nAs people start using a new Node server library other than [Express](https://expressjs.com/), they encounter a lack of middlewares that Express already has, which have been well tested and production-ready many years ago. Some of them try to shape a brand new ecosystem on the new island and some just go back to Express.\n\nLet's start from admitting Express is one of the most successful, beautifully designed and battle-tested software in the Node ecosystem. Don't forget its **hundreds of outstanding middlewares** have been born on it. Then why you can't use them? The answers will be summarized:\n\n* It breaks since they depend on `req.param()` and `res.redirect()` that Express decorates native objects with. I don't want to hack to make them work in my _${Your favorite server comes here}_.\n* Pollution. [Express officially recommends](https://expressjs.com/en/guide/writing-middleware.html) middlewares to extend object properties such as `req.session` and `req.flash`, just where my _${Your favorite server}_ leaves them tidy. Plus, dynamic extensions don't fit today of the TypeScript era.\n\nYeah. Let's move on.\n\n# How\n\nJavaScript `Proxy`.\n\nWrapping `req` and `res` by `Proxy` to split using native methods and Express methods. Express exports clean prototypes that we can intercept internal calls with. It lets middlewares to call native methods like `res.writeHead()` and `res.end()` so native objects properly embed HTTP info and send the response.\n\nIn the end, flow-middleware returns the extended properties like `req.session` and `req.user` so you can use them after the middlewares go through.\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n![flow-middleware architecture](resource/flow-middleware.png)\n\n# Getting started\n\nInstall it with Express.\n\n```bash\nyarn add flow-middleware express\n```\n\n### flow(...middlewares)\n\nA function `flow` creates an http handler from some Express middlewares, processed from left to right of arguments.\n\n```typescript\nimport flow from 'flow-middleware';\nimport { ok } from \"assert\";\nimport { createServer } from 'http';\nimport cookieParser from 'cookie-parser';\nimport session from 'express-session';\nimport flash from 'express-flash';\n\n// Creates an async function that handles req and res.\nconst handle = flow(\n    cookieParser(),\n    session({ secret: 'x' }),\n    flash(),\n    (reqProxy, _resProxy, next) =\u003e {\n    \n        // Our wrapped objects provide accessors\n        // that Express middlewares extended💪\n        ok(reqProxy.cookies);\n        ok(reqProxy.session);\n        ok(reqProxy.flash);\n        next();\n    }\n);\n\ncreateServer(async (req, res) =\u003e {\n  \n    // Let's run the Express middlewares🚀\n    const [ reqProxy, resProxy ] = await handle(req, res);\n\n    // Native objects are clean thanks to our proxy✨\n    ok(req.cookies === undefined);\n    ok(req.session === undefined);\n    ok(req.flash === undefined);\n\n    // You still can access to Express properties here🚚\n    ok(reqProxy.cookies);\n    ok(reqProxy.session);\n    ok(reqProxy.flash);\n    ok(resProxy.cookie);\n    ok(resProxy.redirect);\n\n    res.end('Hello!');\n}).listen(3000);\n```\n\n### compose(...middlewares)(...middlewares)()\n\n`compose` lets you hold a set of middlewares and share it on other routes. This is useful when you want the same initializing middlewares to come first while the different middlewares come at the end. **Calling it with zero arguments returns a handler function.** \n\nThis is a Passport example where a login handler for `POST /api/auth/github` and an OAuth callback handler for `GET /api/auth/callback/github` share their initializing middlewares.\n\n```typescript\nimport cookieSession from 'cookie-session';\nimport { compose } from 'flow-middleware';\nimport passport from './passport';\n\nconst composed = compose(\n    cookieSession(),\n    passport.initialize(),\n    passport.session()\n);\n\nconst handleToLogIn = composed(passport.authenticate('github'))();\n\nconst handleForCallback = composed(passport.authenticate('github', {\n    failureRedirect: '/auth',\n    successRedirect: '/',\n}))();\n```\n\nDon't forget to call it with zero arguments at last to get a handler.\n\n#### Wrapper function style\n\nOr, you can simply write a wrapper function to share middlewares.\n\n```typescript\nimport { Handler } from 'express';\n\nfunction withPassport(...middlewares: Handler[]) {\n    return flow(\n        cookieSession(),\n        passport.initialize(),\n        passport.session(),\n        ...middlewares\n    );\n}\n```\n\n# License\n\nMIT\n\n# Author\n\nSoichi Takamura \\\u003cthepiglovesyou@gmail.com\u003e\n","funding_links":[],"categories":["Extensions","TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiglovesyou%2Fflow-middleware","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiglovesyou%2Fflow-middleware","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiglovesyou%2Fflow-middleware/lists"}