Co Compose Middleware
Co-compose is a lightweight, framework-agnostic middleware composition library for JavaScript and TypeScript applications, inspired by patterns found in Koa and AdonisJS. It enables developers to define an array of asynchronous functions (middleware) and execute them sequentially, with explicit control flow via a `next()` function. The current stable version is 7.0.3, which primarily includes dependency updates and minor fixes. Major versions, like v7, tend to update Node.js compatibility requirements, with minor and patch releases focusing on performance improvements and dependency hygiene. Key differentiators include its reported high performance (benchmarked against alternatives like `fastseries` and `middie`), flexibility with custom executors for different middleware shapes (e.g., ES6 classes), and a dedicated final handler mechanism. It ships with full TypeScript types, making it suitable for modern typed environments.
Common errors
-
TypeError: next is not a function
cause A middleware function attempted to call `next()` but `next` was either not passed as an argument or was not a function (e.g., due to an incorrect middleware signature or custom executor setup).fixEnsure your middleware function correctly accepts `next` as an argument (e.g., `async function (ctx, next) { ... }`) and that `next()` is called as `await next()`. -
SyntaxError: await is only valid in async functions and the top level bodies of modules
cause The `await` keyword was used inside a middleware function that was not declared as `async`.fixAlways declare your middleware functions with the `async` keyword when using `await`, for example: `async function myMiddleware(ctx, next) { await next(); }`. -
ReferenceError: Middleware is not defined
cause The `Middleware` class was used without being correctly imported or after `co-compose` was not installed.fixEnsure `co-compose` is installed (`npm install co-compose` or `yarn add co-compose`) and that `Middleware` is imported using `import { Middleware } from 'co-compose'`.
Warnings
- breaking Version 7.0.0 of `co-compose` dropped support for Node.js versions below 16. Projects upgrading to or using `co-compose@7.x.x` must ensure their environment runs Node.js 16 or newer.
- gotcha Middleware functions must explicitly call `await next()` to transfer control to the subsequent middleware in the chain. Failing to call `next()` will prematurely halt the execution flow for any remaining middleware.
- gotcha When implementing custom middleware executors, ensure the executor function correctly instantiates (if needed) and invokes the main method (e.g., `handle`) of your custom middleware object or class, passing all necessary parameters including the `next` function.
Install
-
npm install co-compose -
yarn add co-compose -
pnpm add co-compose
Imports
- Middleware
const { Middleware } = require('co-compose')import { Middleware } from 'co-compose' - MiddlewareHandler
import type { MiddlewareHandler } from 'co-compose' - ExecutorFn
import type { ExecutorFn } from 'co-compose'
Quickstart
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()
}
// Create a new middleware instance
const middleware = new Middleware()
// Register middleware functions
middleware.register([fn1, fn2])
// Run the middleware chain with optional context
async function runChain() {
const ctx = { data: 'initial' }
await middleware.runner().run([ctx])
console.log('Middleware chain finished.')
}
runChain().catch(console.error)