3.0.0 • Published 7 years ago

ctx-compose v3.0.0

Weekly downloads
8
License
MIT
Repository
github
Last release
7 years ago

ctx-compose

NPM version Dependency Status License Downloads

: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

3.0.0

7 years ago

2.0.0

7 years ago

1.2.0

7 years ago

1.1.0

7 years ago