A generic middleware pattern in Typescript
I just realized this is the third time I’m writing async middleware invoker, I thought I would share the generic pattern for the benefit of others.
I’m not sure if this is interesting enough for a NPM package, so I’ll leave it here for inspiration.
The specific middleware pattern I am implementing, is similar to Express, Koa or Curveball.
We’re working off a context
, and we are running a chain of middlewares
in order with this context as an argument.
We’re also passing an next
function. If this next
function is called,
the next middleware in the list will be called. If not, the chain will be
broken.
Furthermore, (unlike Express, but like Koa) middlewares can be async
function or return a promise. If it is, we want to await it.
The setup
Lets start with the setup, describing the middleware:
/**
* 'next' function, passed to a middleware
*/
type Next = () => void | Promise<void>;
/**
* A middleware
*/
type Middleware<T> =
(context: T, next: Next) => Promise<void> | void;
Middleware
is the actual async/non-async middleware function. I made a
type for Next
so I don’t need to write it out more than once.
How we want to use it
This would be the ‘getting started’ section of the documentation.
The idea here is that we have an ‘app’, a set of middlewares and a context we want to operate on.
The following code would be written by the user of this framework:
/**
* The context type of the application.
*
* In 'koa' this object would hold a reference to the 'request' and 'response'
* But our context just has a single property.
*/
type MyContext = {
a: number;
}
/**
* Creating the application object
*/
const app = new MwDispatcher<MyContext>();
/**
* A middleware
*/
app.use((context: MyContext, next: Next) => {
context.a += 1;
return next();
});
/**
* An async middleware
*/
app.use(async (context: MyContext, next: Next) =>
Truncated by Planet PHP, read more at the original (another 5860 bytes)