3.0.0 • Published 7 years ago
ctx-compose v3.0.0
ctx-compose
:globe_with_meridians: Universal middleware composing library based on koajs/koa-compose. Works with asynchronous and synchronous middleware on browsers, Node.js and React-Native.
Create your own middleware-based module!
Installation
npm install ctx-compose
# or:
yarn add ctx-compose
Usage
Import this module with:
// Module import
import { compose, composeSync } from "ctx-compose";
// CommonJS import
const { compose, composeSync } = require("ctx-compose");
// Specific and lightweight import
const compose = require("ctx-compose/async");
const composeSync = require("ctx-compose/sync");
// "Functional" wrapper
const compose = require("ctx-compose/fp/async");
const composeSync = require("ctx-compose/fp/sync");
And it is used like this:
const middleware = [/* ... */];
const context = {}; // it gets mutated along the middlewares
// Asynchronous:
await compose(middleware)(context);
// Synchronous:
composeSync(middleware)(context);
console.log(context);
Asynchronous
The compose
function works exactly as Koa middlewares and supports asynchronous and synchronous middleware.
const compose = require("ctx-compose/async");
const Bluebird = require("bluebird");
async function log(ctx, next) {
console.log(">>>", ctx.value);
await next();
console.log("<<<", ctx.value);
}
async function increaser(ctx) {
await Bluebird.delay(1000); // wait 1000ms
ctx.value = ctx.value + 1;
}
const context = { value: 4 };
const middleware = [log, increaser];
compose(middleware)(context)
.then(() => {
console.log("Value:", context.value);
})
.catch(err => {
console.error(err);
});
Synchronous
The composeSync
middleware works like this. It doesn't support async middleware:
const composeSync = require("ctx-compose/sync");
function log(ctx, next) {
console.log(">>>", ctx.value);
next();
console.log("<<<", ctx.value);
}
function increaser(ctx) {
ctx.value = ctx.value + 1;
}
const context = { value: 4 };
const middleware = [log, increaser];
try {
composeSync(middleware)(context);
console.log("Value:", context.value);
} catch (err) {
console.error(err);
}
Console output:
>>> 4
<<< 5
Value: 5
Functional mode
For convenience, you can use this wrapper that creates a shallow copy of the context
object before each layer of middleware (if needed) and return the final object as the result.
You can use a custom copy
function as the second argument of compose
. By default it uses:
function copy(ctx) {
return Object.assign({}, ctx);
}
Asynchronous
const compose = require("ctx-compose/fp/async");
const Bluebird = require("bluebird");
async function log(ctx, next) {
console.log(">>>", ctx.value);
const nextCtx = await next();
console.log("<<<", nextCtx.value);
return nextCtx; // Explicit context return.
}
async function increaser(ctx) {
await Bluebird.delay(1000); // wait 1000ms
ctx.value = ctx.value + 1;
return ctx; // Explicit context return.
}
const middleware = [log, increaser];
compose(middleware)({ value: 4 })
.then(context => {
console.log("Value:", context.value);
})
.catch(err => {
console.error(err);
});
const composeSync = require("ctx-compose/fp/sync");
function log(ctx, next) {
console.log(">>>", ctx.value);
const nextCtx = next();
console.log("<<<", nextCtx.value);
return nextCtx; // Explicit context return.
}
function increaser(ctx) {
ctx.value = ctx.value + 1;
return ctx; // Explicit context return.
}
const middleware = [log, increaser];
try {
const context = composeSync(middleware)({ value: 4 });
console.log("Value:", context.value);
} catch (err) {
console.error(err);
}
License
MIT