1.0.0 • Published 4 years ago

middlewarer v1.0.0

Weekly downloads
1
License
AGPL-3.0
Repository
github
Last release
4 years ago

Middlewarer

Middleware execution chain library.

npm

Creates callable middleware chains, similar to those used by express#use.

Callbacks in the chain are passed a variable number of arguments followed by a next callback which can be called to pass execution on to the next callback in the chain.

This library also exposes TypeScript helper types (and Async variants) Callable, Consumer, Provider, and Runnable, similar to those from Java.

Installation

$ yarn add middlewarer

or, with NPM

$ npm install middlewarer

Usage

CommonJS:

const { AsyncController, Controller } = require("middlewarer");

ES Modules/TypeScript:

import { AsyncController, Controller } from "middlewarer";

Controller#chain(callback: (...args, next) => any): Controller

Adds a callback to the chain. next is a callback which invokes the next callback in the chain and should be called by your callback except in conditions where the chain should be stopped. next does not accept any parameters.

If you wish to maintain a shared state between chain steps, you should modify an external variable or pass a state object to Controller#run.

Controller#run(...args): Controller

Starts the chain execution. Note: if all functions in the chain are synchronous, then this call will also be synchronous. However, if any function is asynchronous in how it calls next(), then this function will return once that async execution begins.

If you need to perform all asynchronous functions before returning from run, use an AsyncController instead.

AsyncController#chain(callback: (...args, next) => Promise<any>): AsyncController

Identical to Controller#chain, except callback should be Promise-returning and next is asynchrnous, and thus should be called with await.

AsyncController#run(...args): Promise<AsyncController>

Similar to Controller#run. Executes and awaits all chained callbacks.


Synchronous Example

import { Controller, Runnable } from "middlewarer";

const controller = new Controller<[number]>(); // Callback parameter type array

controller
  .chain((num, next) => {
    console.log(`Chain 0: ${num}`);
    next(); // Continues chain
  })
  .chain((num, next) => {
    console.log(`Chain 1: ${num}`);
    if (num === 42) next(); // Only continue chain if num is 42
  })
  .chain((num, next) => {
    console.log(`The answer has been found. You just lost The Game.`);
  });

// ... Later (or in function chain), call the controller

controller.run(4); // Will get to chain 0 and 1, but not the answer

controller.run(42); // Will trigger all three chained callbacks

Asynchronous Example

import { AsyncController, Runnable } from "middlewarer";

// A dummy representing an asynchronous API call
async function checkAnswer(value: number): Promise<boolean> {
  return value === 42;
}

const controller = new AsyncController<[number]>();

controller
  .chain(async (num, next) => {
    console.log(`Chain 0: ${num}`);
    await next();
  })
  .chain(async (num, next) => {
    console.log(`Chain 1: ${num}`);
    if (await checkAnswer(num)) await next(); // Continue dependent on async API result
  })
  .chain(async (num, next) => {
    console.log(`The answer has been found. You just lost The Game.`);
  });

await controller.run(4);

await controller.run(42);

License

Licensed under the GNU Affero General Public License v3.0 license. See LICENSE in the root of this project or https://www.gnu.org/licenses/agpl-3.0.en.html for more info.

Copyright © 2020 Brenden Campbell.