middlewarer
v1.0.0
Published
Middleware execution chain library
Downloads
4
Maintainers
Readme
Middlewarer
Middleware execution chain library.
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 await
s 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.