@akala/core
Version:
148 lines • 6.04 kB
JavaScript
import { each as eachAsync } from '../eachAsync.js';
import { NotHandled, convertToErrorMiddleware, convertToMiddleware, isErrorMiddleware, isStandardMiddleware } from './shared.js';
/**
* A composite middleware class with priority for asynchronous operations.
* @template T - The type of the arguments.
* @template TSpecialNextParam - The type of the special next parameter.
*/
export class MiddlewareCompositeWithPriorityAsync {
name;
/**
* Creates an instance of MiddlewareCompositeWithPriorityAsync.
* @param {string} [name] - The name of the middleware composite.
*/
constructor(name) {
this.name = name;
}
stack = [];
/**
* Adds middleware to the stack with a specified priority.
* @param {number} priority - The priority of the middleware (the lowest first).
* @param {...AnyAsyncMiddleware<T, TSpecialNextParam>[]} middlewares - The middlewares to add.
* @returns {this} The instance of the middleware composite.
*/
useMiddleware(priority, ...middlewares) {
this.stack.push(...middlewares.map(m => [priority, m]));
this.stack.sort((a, b) => a[0] - b[0]);
return this;
}
/**
* Adds standard middleware to the stack with a specified priority.
* @param {number} priority - The priority of the middleware (the lowest first).
* @param {...((...args: T) => Promise<unknown>)[]} middlewares - The middlewares to add.
* @returns {this} The instance of the middleware composite.
*/
use(priority, ...middlewares) {
return this.useMiddleware(priority, ...middlewares.map(m => convertToMiddleware(m)));
}
/**
* Adds error middleware to the stack with a specified priority.
* @param {number} priority - The priority of the middleware (the lowest first).
* @param {...((error: Error | OptionsResponse, ...args: T) => Promise<unknown>)[]} middlewares - The middlewares to add.
* @returns {this} The instance of the middleware composite.
*/
useError(priority, ...middlewares) {
return this.useMiddleware(priority, ...middlewares.map(m => convertToErrorMiddleware(m)));
}
/**
* Processes the request and returns a promise.
* @template X - The type of the return value.
* @param {...T} req - The request arguments.
* @returns {Promise<X>} A promise that resolves or rejects with the result.
*/
process(...req) {
return this.handle(...req).then(x => Promise.reject(x), x => Promise.resolve(x));
}
/**
* Handles errors in the middleware stack.
* @param {Error | OptionsResponse} error - The error to handle.
* @param {...T} req - The request arguments.
* @returns {MiddlewarePromise} A promise that resolves or rejects with the result.
*/
async handleError(error, ...req) {
let failed = !!error;
// this.stack.sort((a, b) => a[0] - b[0]);
try {
if (this.stack.length === 0)
return error;
await eachAsync(this.stack, async (middleware) => {
try {
if (failed && isErrorMiddleware(middleware[1])) {
const err = await middleware[1].handleError(error, ...req);
if (err === 'break')
throw err;
if (typeof err != 'string' && typeof err != 'undefined')
error = err;
failed = true;
}
}
catch (x) {
throw { success: x };
}
}, true);
return error;
}
catch (err) {
switch (typeof err) {
case 'string':
return;
case 'undefined':
return error;
default:
throw err.success;
}
}
}
/**
* Handles the middleware stack.
* @param {...T} req - The request arguments.
* @returns {MiddlewarePromise<TSpecialNextParam>} A promise that resolves or rejects with the result.
*/
async handle(...req) {
let error = undefined;
let failed = undefined;
// this.stack.sort((a, b) => a[0] - b[0]);
try {
if (this.stack.length === 0)
return error;
await eachAsync(this.stack, (middleware) => {
if (failed && isErrorMiddleware(middleware[1])) {
return middleware[1].handleError(error, ...req).then(err => {
if (err === 'break')
throw err;
if (typeof err != 'string' && typeof err != 'undefined')
error = err;
failed = true;
}, e => Promise.reject({ success: e }));
}
else if (!failed && isStandardMiddleware(middleware[1])) {
return middleware[1].handle(...req).then(err => {
if (err === 'break')
throw err;
if (typeof err != 'string' && typeof err != 'undefined') {
if (err['allow'])
error['allow'].push(...err['allow']);
else
error = err;
}
failed = err instanceof Error;
}, e => Promise.reject({ success: e }));
}
else
return NotHandled;
}, true);
return error;
}
catch (err) {
switch (typeof err) {
case 'string':
return;
case 'undefined':
return error;
default:
throw err.success;
}
}
}
}
//# sourceMappingURL=composite-with-priority-async.js.map