koa-compose

raw JSON →
4.1.0 verified Sat Apr 25 auth: no javascript

Utility to compose Koa middleware functions into a single middleware. Current stable version is 4.1.0. Low release cadence; maintained as part of the Koa ecosystem. Key differentiator: it is the canonical middleware composition function for Koa, supporting async/await and error handling through promises. Alternatives like `koa-convert` or custom loops exist, but this is minimal and standard.

error TypeError: middleware is not a function
cause Passing non-array or undefined to compose.
fix
Ensure compose is called with an array: compose([func1, func2])
error Error: next() called multiple times
cause Calling next() more than once in a middleware function.
fix
Ensure each middleware calls next() exactly once, or handle conditional logic properly.
error ReferenceError: compose is not defined
cause Missing import or using incorrect import syntax.
fix
Use proper import: import compose from 'koa-compose' or const compose = require('koa-compose')
gotcha compose expects an array of middleware; passing non-array will throw.
fix Always wrap middleware in an array: compose([mw1, mw2])
gotcha Middleware must be async functions returning Promises; otherwise compose may not work correctly.
fix Define middleware as async (ctx, next) => { await next(); }
gotcha compose returns a single middleware function; cannot be used directly as router-level middleware without wrapping.
fix Use the returned function with app.use() or router middleware stack.
npm install koa-compose
yarn add koa-compose
pnpm add koa-compose

Demonstrates composing two Koa middleware functions (logger and responseTime) using compose, then applying to a Koa app.

import Koa from 'koa';
import compose from 'koa-compose';

const app = new Koa();

const logger = async (ctx, next) => {
  console.log(`${ctx.method} ${ctx.url}`);
  await next();
};

const responseTime = async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  ctx.set('X-Response-Time', `${ms}ms`);
};

const composed = compose([logger, responseTime]);

app.use(composed);
app.listen(3000);
console.log('Server running on port 3000');