UNPKG

@akala/core

Version:
160 lines 6.3 kB
import { each } from '../each.js'; import { process, convertToErrorMiddleware, convertToMiddleware, isErrorMiddleware, isStandardMiddleware } from './shared.js'; /** * A composite middleware class that allows for the composition of multiple middlewares. */ export class MiddlewareComposite { name; /** * Creates an instance of MiddlewareComposite. * @param {string} [name] - The name of the middleware composite. */ constructor(name) { this.name = name; } /** * Creates a new MiddlewareComposite instance with the provided middlewares. * @param {...AnySyncMiddleware<T>[]} middlewares - The middlewares to be used. * @returns {MiddlewareComposite<T>} A new MiddlewareComposite instance. */ static new(...middlewares) { return new MiddlewareComposite().useMiddleware(...middlewares); } stack = []; /** * Adds middlewares to the stack. * @param {...AnySyncMiddleware<T, TSpecialNextParam>[]} middlewares - The middlewares to be added. * @returns {this} The current instance of MiddlewareComposite. */ useMiddleware(...middlewares) { this.stack.push(...middlewares); return this; } /** * Adds middlewares to the stack. * @param {...((...args: T) => unknown)[]} middlewares - The middlewares to be added. * @returns {this} The current instance of MiddlewareComposite. */ use(...middlewares) { return this.useMiddleware(...middlewares.map(m => convertToMiddleware(m))); } /** * Adds error middlewares to the stack. * @param {...((error: Error | OptionsResponse, ...args: T) => unknown)[]} middlewares - The error middlewares to be added. * @returns {this} The current instance of MiddlewareComposite. */ useError(...middlewares) { return this.useMiddleware(...middlewares.map(convertToErrorMiddleware)); } /** * Processes the request using the middlewares in the stack. * @param {...T} req - The request parameters. * @returns {X} The result of the processing. */ process(...req) { return process(this, ...req); } /** * Handles errors by processing them through registered error-handling middlewares in the stack. * * This method iterates over each error middleware, allowing them to attempt resolving the error. * Middlewares can return a modified error, propagate it further, or halt processing with 'break'. * * @param {MiddlewareResult<TSpecialNextParam>} error - The initial error object to handle * @param {...T} req - The original request parameters associated with the error * @returns {MiddlewareResult<TSpecialNextParam>} The final resolved error or successful result after processing */ handleError(error, ...req) { let failed = !!error; try { if (this.stack.length === 0) return error; each(this.stack, async (middleware) => { try { if (failed && isErrorMiddleware(middleware)) { const err = middleware.handleError(error, ...req); if (err === 'break') throw err; if (typeof err != 'string' && typeof err != 'undefined') error = err; failed = true; } } catch (x) { throw { success: x }; } }); return error; } catch (err) { switch (typeof err) { case 'string': return; case 'undefined': return error; default: throw err.success; } } } /** * Processes the request through all registered middlewares in the stack. * * This method iterates over each middleware in the stack, applying standard middlewares first until an error occurs. * Once an error is detected, subsequent error-handling middlewares take over to resolve or propagate the error. * * @param {...T} req - The request parameters passed to the middleware stack * @returns {MiddlewareResult<TSpecialNextParam>} The final result from the middleware processing, which may include: * - An Error instance if an unhandled error occurred * - A special 'next' parameter indicating continuation behavior * - Custom response objects based on middleware logic */ handle(...req) { let error = undefined; let failed = undefined; try { if (this.stack.length === 0) return error; each(this.stack, (middleware) => { if (failed && isErrorMiddleware(middleware)) { const err = middleware.handleError(error, ...req); if (err === 'break') throw err; if (typeof err != 'string' && typeof err != 'undefined') error = err; failed = true; } else if (!failed && isStandardMiddleware(middleware)) { let err; try { err = middleware.handle(...req); } catch (e) { throw { success: e }; } 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; } }); return error; } catch (err) { switch (typeof err) { case 'string': return; case 'undefined': return error; default: throw err.success; } } } } //# sourceMappingURL=composite-sync.js.map