UNPKG

co-compose

Version:

AdonisJS and Koa style middleware layer with ability to run parallel middleware

165 lines (118 loc) 4.47 kB
<div align="center"> <img src="https://res.cloudinary.com/adonisjs/image/upload/q_100/v1557762307/poppinss_iftxlt.jpg" width="600px"> </div> # Co Compose > Compose an array of functions to be executed one after the other. Similar to Koa and AdonisJS middlewares. [![gh-workflow-image]][gh-workflow-url] [![typescript-image]][typescript-url] [![npm-image]][npm-url] [![license-image]][license-url] [![synk-image]][synk-url] Co compose composes an array of middleware to be executed in sequence. The library is framework independent and can be used in any Javascript/Typescript project. <details> <summary> <strong>Benchmarks (v16.5.0)</strong> </summary> Co Compose x 2,145,829 ops/sec ±0.16% (90 runs sampled) fastseries x 166,990 ops/sec ±2.04% (64 runs sampled) middie x 122,162 ops/sec ±7.84% (28 runs sampled) <p> <strong> Fastest is Co Compose </strong> </p> </details> <!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> ## Table of contents - [Installation](#installation) - [Usage](#usage) - [Passing values](#passing-values) - [Custom executors](#custom-executors) - [Final Handler](#final-handler) <!-- END doctoc generated TOC please keep comment here to allow auto update --> ## Installation ```sh npm i co-compose # yarn yarn add co-compose ``` ## Usage Checkout the following example to run an array of middleware functions. ```ts import { Middleware } from 'co-compose' async function fn1(next) { console.log('executing fn1') await next() } async function fn2(next) { console.log('executing fn2') await next() } const middleware = new Middleware() middleware.register([fn1, fn2]) await middleware.runner().run([]) ``` ### Passing values You can also pass values to all middleware functions. An `array` of values passed to `runner.run()` will be passed to middleware functions as multiple arguments. ```js async function fn1(ctx, next) { ctx.stack.push('fn1') await next() } async function fn2(ctx, next) { ctx.stack.push('fn2') await next() } const ctx = { stack: [], } await middleware.runner().run([ctx]) assert.deepEqual(ctx.stack, ['fn1', 'fn2']) ``` ### Custom executors The default behavior is to define middleware as functions. However, you can define them in any shape and then stick a custom executor to execute them. Check the following example where `ES6 classes` are used. ```js class Middleware1 { async handle(ctx, next) { ctx.stack.push('fn1') await next() } } class Middleware2 { async handle(ctx, next) { ctx.stack.push('fn2') await next() } } const middleware = new Middleware() const ctx = { stack: [], } middleware.register([Middleware1, Middleware2]) await middleware .runner() .executor(async function (MiddlewareClass, params) { const instance = new MiddlewareClass() // 👈 await instance.handle(...params) // 👈 }) .run([ctx]) ``` ### Final Handler The final handler is a executed when the entire middleware chain ends by calling `next`. This makes it easier to execute custom functions, which are not part of the chain, however must be executed when chain ends. > Also, the arguments for the final handler can be different from the middleware arguments ```js async function fn1(ctx, next) { ctx.stack.push('fn1') await next() } async function finalHandler() { ctx.stack.push('final handler') } const ctx = { stack: [], } await middleware.runner().finalHandler(finalHandler, [ctx]).run([ctx]) assert.deepEqual(ctx.stack, ['fn1', 'final handler']) ``` [gh-workflow-image]: https://img.shields.io/github/workflow/status/poppinss/co-compose/test?style=for-the-badge [gh-workflow-url]: https://github.com/poppinss/co-compose/actions/workflows/test.yml "Github action" [typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript [typescript-url]: "typescript" [npm-image]: https://img.shields.io/npm/v/co-compose.svg?style=for-the-badge&logo=npm [npm-url]: https://npmjs.org/package/co-compose 'npm' [license-image]: https://img.shields.io/npm/l/co-compose?color=blueviolet&style=for-the-badge [license-url]: LICENSE.md 'license' [synk-image]: https://img.shields.io/snyk/vulnerabilities/github/poppinss/co-compose?label=Synk%20Vulnerabilities&style=for-the-badge [synk-url]: https://snyk.io/test/github/poppinss/co-compose?targetFile=package.json 'synk'