Modern Promise-Based Middleware

2.8.1 · maintenance · verified Wed Apr 22

middleware-io is a lightweight, zero-dependency library for composing promise-based middleware in JavaScript and TypeScript applications. It provides a `compose` function similar to `koa-compose` and a `Composer` class for building middleware chains with various utility 'snippets' like lazy loading, forking, and concurrency control. The library is written in TypeScript, ensuring type safety and a robust development experience. Currently at version 2.8.1, its release cadence has been irregular since its active development phase around 2019-2021, with the latest significant changes related to `exports` in `package.json` for modern module resolution. Key differentiators include its self-sufficiency (zero dependencies), native ESM support, and a rich set of built-in middleware snippets.

Common errors

Warnings

Install

Imports

Quickstart

This example demonstrates basic promise-based middleware composition, context modification, and asynchronous flow control using `compose`.

import { compose } from 'middleware-io';

interface MyContext {
  now?: number;
  customData?: string;
}

const composedMiddleware = compose<MyContext>([
  async (context, next) => {
    // This is the first middleware in the chain.
    console.log('Step 1: Before next() in first middleware');

    // Pass control to the next middleware in the stack.
    await next();

    // Control returns here after subsequent middleware complete.
    console.log('Step 4: After next() in first middleware');

    // Access data modified by later middleware.
    console.log(`Context.now from next middleware: ${context.now}`);
  },
  async (context, next) => {
    // This is the second middleware.
    console.log('Step 2: Before next() in second middleware');

    // Modify the context object, which is shared across the chain.
    context.now = Date.now();
    context.customData = 'Hello from second middleware!';

    // Pass control to the next middleware (or the final handler if no more middleware).
    await next();

    // Control returns here after the next middleware (or final handler) completes.
    console.log('Step 3: After next() in second middleware');
  }
]);

// Execute the composed middleware with an initial context and a final handler.
composedMiddleware({}, () => {
  console.log('Final handler reached (no more middleware).');
  return Promise.resolve(); // Ensure the final handler also returns a Promise
})
  .then(() => {
    console.log('Middleware chain finished work successfully.');
  })
  .catch(console.error);

view raw JSON →