co-compose
Version:
AdonisJS and Koa style middleware layer with ability to run parallel middleware
86 lines (85 loc) • 2.44 kB
JavaScript
"use strict";
/*
* co-compose
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Runnable = void 0;
/**
* Default final handler resolves the middleware chain right away
*/
const DEFAULT_FINAL_HANDLER = {
fn: () => Promise.resolve(),
args: [],
};
/**
* The default executor to execute middlewares. This method assumes middleware
* as functions and calls them right away
*/
const DEFAULT_EXECUTOR = (fn, params) => fn(...params);
/**
* Runnable to execute an array of functions in sequence. The queue is
* advanced only when the current function calls `next`.
*
* @example
* ```js
* const runner = new Runnable([async function fn1 (params, next) {
* }])
* ```
*/
class Runnable {
constructor(list) {
this.list = list;
this.index = 0;
this.params = [];
this.executorFn = DEFAULT_EXECUTOR;
this.registeredFinalHandler = DEFAULT_FINAL_HANDLER;
}
/**
* Invoke one middleware at a time. Middleware fns will be executed
* recursively until `next` is invoked.
*
* If one method doesn't call `next`, then the chain will be finished
* automatically.
*/
invoke() {
const fn = this.list[this.index++];
/**
* Empty stack
*/
if (!fn) {
return this.registeredFinalHandler.fn(...this.registeredFinalHandler.args);
}
return this.executorFn(fn, this.params);
}
/**
* Final handler to be executed, when chain ends successfully
*/
finalHandler(fn, args) {
this.registeredFinalHandler = { fn, args };
return this;
}
/**
* Define custom resolver, which is invoked for all the middleware.
* If this method is defined, then default executor is not called
* and it's the responsibility of this method to call the
* middleware and pass params to it
*/
executor(fn) {
this.executorFn = fn;
return this;
}
/**
* Start the middleware queue and pass params to it. The `params`
* array will be passed as spread arguments.
*/
async run(params) {
this.params = params.concat(this.invoke.bind(this));
return this.invoke();
}
}
exports.Runnable = Runnable;