Monadic Middleware
npm install --save monastic fluture momi
Middleware - specifically in the case of Connect, Express and Koa - is a mechanism which encodes several effects:
- A build-up of state through mutation of the
req
parameter - An eventual response through mutation of the
res
parameter - Inversion of control over the continuation by means of calling the
next
parameter - Possible error branch by means of calling the
next
parameter with a value
If we would want to encode all of these effects into a data-structure, we
could use a StateT(Future) -> StateT(Future)
structure:
- A build-up of state through the
State
monad - An eventual response through the right-sided value of
Future
- Inversion of control by passing the whole structure into a function
- Possible error branch through the left-sided value of
Future
In other words, the StateT(Future)
-structure might be considered the
Middleware monad. This packages exposes the Middleware monad, comprised of
State
from monastic and Future
from Fluture. Besides the
monad itself, it also exposes some utility functions and structures for
practically applying Middleware. One such utility is the App
class,
which allows composition of functions over Middleware to be written more
like what you are used to from middleware as it comes with Express or Koa.
$ npm install --save momi
On Node 12 and up, this module can be loaded directly with import
or
require
. On Node versions below 12, require
or the esm-loader can
be used.
You can load the EcmaScript module from various content delivery networks:
There's a UMD file included in the NPM package, also available via jsDelivr: https://cdn.jsdelivr.net/npm/momi@1.0.0/dist/umd.js
This file adds momi
to the global scope, or use CommonJS/AMD
when available.
import Z from 'sanctuary-type-classes';
import qs from 'querystring';
import http from 'http';
import {compose, constant} from 'monastic';
import {go, mount, get, put} from 'momi';
const queryParseMiddleware = go (function* (next) {
const req = yield get;
const query = qs.parse (req.url.split ('?')[1]);
yield put (Object.assign ({query}, req));
return yield next;
});
const echoMiddleware = Z.map (req => ({
status: 200,
headers: {'X-Powered-By': 'momi'},
body: req.query.echo,
}), get);
const app = compose (
queryParseMiddleware,
constant (echoMiddleware)
);
mount (http, app, 3000);
- Readme the code from Usage, ready to run.
- Express shows how to embed Momi within Express.
- Bootstrap an example showing application structure.
- Real World how momi is being used in real life.