Compose multiple middleware functions into one that runs them one after another, each receiving the context and a next that continues the chain. Commonly used to build middleware systems, such as Koa-style middleware.
Argument
Description
Type
Function
Composed middleware function
ComposedMiddleware<T>
Parameter
Description
Type
Default
middleware
Array of middleware functions
Array<Middleware<T>>
Required
type Middleware < T > = ( context : T , next : Next ) => any ;
type Next = () => Promise < never > | Promise < void >;
import { compose } from 'ranuts' ;
const middleware1 = async ( ctx , next ) => {
console. log ( 'Middleware 1 start' );
await next ();
console. log ( 'Middleware 1 end' );
};
const middleware2 = async ( ctx , next ) => {
console. log ( 'Middleware 2 start' );
await next ();
console. log ( 'Middleware 2 end' );
};
const middleware3 = async ( ctx , next ) => {
console. log ( 'Middleware 3 execute' );
ctx.data = 'Processed' ;
};
const composed = compose ([middleware1, middleware2, middleware3]);
const context = {};
await composed (context);
// Output:
// Middleware 1 start
// Middleware 2 start
// Middleware 3 execute
// Middleware 2 end
// Middleware 1 end
console. log (context.data); // 'Processed'
import { compose } from 'ranuts' ;
// Logger middleware
const logger = async ( req , next ) => {
console. log ( `[${ new Date (). toISOString () }] ${ req . method } ${ req . url }` );
await next ();
};
// Auth middleware
const auth = async ( req , next ) => {
if ( ! req.headers.authorization) {
throw new Error ( 'Unauthorized' );
}
await next ();
};
// Handler middleware
const handler = async ( req , next ) => {
req.response = { message: 'Hello World' };
};
const app = compose ([logger, auth, handler]);
const request = {
method: 'GET' ,
url: '/api/users' ,
headers: { authorization: 'Bearer token123' },
};
await app (request);
console. log (request.response); // { message: 'Hello World' }
import { compose } from 'ranuts' ;
const errorHandler = async ( ctx , next ) => {
try {
await next ();
} catch (error) {
console. error ( 'Error:' , error.message);
ctx.error = error;
}
};
const handler = async ( ctx , next ) => {
throw new Error ( 'Processing failed' );
};
const composed = compose ([errorHandler, handler]);
const context = {};
await composed (context);
console. log (context.error); // Error: Processing failed
Execution order : Middleware executes in array order, and the next middleware executes after calling next().
Async support : All middleware should be async functions or return Promises.
next() call : Must call next() in middleware to continue to the next middleware.
Multiple calls : Cannot call next() multiple times, otherwise an error will be thrown.
Context passing : Pass data between middleware through the context object.