UNPKG

@halsp/core

Version:

面向云的现代渐进式轻量 Node.js 框架

123 lines 3.69 kB
import { isClass, isObject } from "../utils/index.mjs"; import { HookType } from "../hook/index.mjs"; import { execConstructorHooks, execErrorHooks, execHooks, execUnhandledHooks, } from "../hook/hook.exec.mjs"; function isMiddlewareConstructor(md) { return !!md.prototype; } export async function createMiddleware(ctx, middleware) { if (middleware instanceof Middleware) { return middleware; } else if (isMiddlewareConstructor(middleware)) { return await execConstructorHooks(ctx, middleware); } else if (Array.isArray(middleware)) { return createMiddleware(ctx, await middleware[0](ctx)); } else { return createMiddleware(ctx, await middleware(ctx)); } } export class Middleware { #index; #mds; #ctx; get ctx() { return this.#ctx; } get req() { return this.#ctx.req; } get request() { return this.#ctx.req; } get res() { return this.#ctx.res; } get response() { return this.#ctx.response; } get logger() { return this.ctx.logger; } set logger(val) { this.ctx.logger = val; } isPrevInstanceOf(target) { const prevMd = this.#mds[this.#index - 1]; return this.#isInstanceOf(prevMd, target); } isNextInstanceOf(target) { const nextMd = this.#mds[this.#index + 1]; return this.#isInstanceOf(nextMd, target); } #isInstanceOf(md, target) { if (!md) return false; if (md == target) return true; if (Array.isArray(md)) { return md[1] == target || md[1].prototype instanceof target; } else if (isClass(md)) { return md.prototype instanceof target; } else { return md instanceof target; } } async next() { let nextMd = undefined; try { if (false == (await execHooks(this.ctx, HookType.BeforeNext, this))) { return; } if (this.#mds.length <= this.#index + 1) return; nextMd = await this.#createNextMiddleware(); nextMd.init(this.ctx, this.#index + 1, this.#mds); if (false == (await execHooks(this.ctx, HookType.BeforeInvoke, nextMd))) { return; } await nextMd.invoke(); await execHooks(this.ctx, HookType.AfterInvoke, nextMd); } catch (err) { const error = err; if (isObject(error) && "breakthrough" in error && error.breakthrough) { throw error; } else { const md = nextMd ?? this; const hookResult = await execErrorHooks(this.ctx, md, error); if (!hookResult) { await execUnhandledHooks(this.ctx, md, error); } } } } #createNextMiddleware = async () => { const middleware = this.#mds[this.#index + 1]; return await createMiddleware(this.ctx, middleware); }; init(ctx, index, mds) { this.#mds = mds; this.#ctx = ctx; this.#index = index; return this; } } export async function invokeMiddlewares(ctx, mds, isRoot = false) { const md = await createMiddleware(ctx, mds[0]); try { await md.init(ctx, 0, mds).invoke(); } catch (err) { const error = err; const hookResult = await execErrorHooks(ctx, md, error); if (isRoot && !hookResult) { await execUnhandledHooks(ctx, md, error); } } } //# sourceMappingURL=middleware.js.map