# co-compose

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

Latest version **7.0.3** (published 2022-11-04) · MIT license · 0 weekly downloads

## Install

```sh
npm install co-compose
pnpm add co-compose
yarn add co-compose
bun add co-compose
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 7.0.3 |
| Published | 2022-11-04 |
| First published | 2016-11-26 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 0 |
| Unpacked size | 14.6 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 30 |
| Author | virk,adonisjs |
| Maintainers | virk |
| Keywords | adonisjs, koa, middleware, co, co-middleware |

## Links

- npm: https://www.npmjs.com/package/co-compose
- Repository: https://github.com/poppinss/co-compose
- Homepage: https://github.com/poppinss/co-compose#readme
- Issues: https://github.com/poppinss/co-compose/issues
- npm.io page: https://npm.io/package/co-compose

## Alternatives

- [flatbuffers](https://npm.io/package/flatbuffers.md) — 6.0M weekly downloads
- [jwt-simple](https://npm.io/package/jwt-simple.md) — 259.5K weekly downloads
- [@exodus/patch-broken-hermes-typed-arrays](https://npm.io/package/@exodus/patch-broken-hermes-typed-arrays.md) — 28.5K weekly downloads
- [@native-to-anchor/buffer-layout](https://npm.io/package/@native-to-anchor/buffer-layout.md) — 12.2K weekly downloads
- [binary-parser-encoder](https://npm.io/package/binary-parser-encoder.md) — 5.3K weekly downloads

## Recent versions

- 7.0.3 (latest) — 2022-11-04
- 7.0.2 — 2022-04-04
- 7.0.1 — 2022-02-22
- 7.0.0 — 2021-12-17
- 6.1.4 — 2021-07-19
- 6.1.3 — 2021-05-31
- 6.1.2 — 2021-05-04
- 6.1.1 — 2021-03-22
- 6.1.0 — 2021-02-08
- 6.0.3 — 2020-09-21
- 6.0.2 — 2020-08-31
- 6.0.1 — 2020-07-18
- 6.0.0 — 2020-07-04
- 5.1.5 — 2020-04-12
- 5.1.4 — 2020-04-08
- … 12 more at https://npm.io/package/co-compose/versions

## README

<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'

---
_Source: https://npm.io/package/co-compose · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
