UNPKG

contexify

Version:

A TypeScript library providing a powerful dependency injection container with context-based IoC capabilities, inspired by LoopBack's Context system.

136 lines 3.96 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); import createDebugger from "../utils/debug.js"; import { transformValueOrPromise } from "../utils/value-promise.js"; const debug = createDebugger("contexify:interceptor-chain"); let InterceptorChainState = class InterceptorChainState2 { static { __name(this, "InterceptorChainState"); } interceptors; finalHandler; _index = 0; /** * Create a state for the interceptor chain * @param interceptors - Interceptor functions or binding keys * @param finalHandler - An optional final handler */ constructor(interceptors, finalHandler = () => void 0) { this.interceptors = interceptors; this.finalHandler = finalHandler; } /** * Get the index for the current interceptor */ get index() { return this._index; } /** * Check if the chain is done - all interceptors are invoked */ done() { return this._index === this.interceptors.length; } /** * Get the next interceptor to be invoked */ next() { if (this.done()) { throw new Error("No more interceptor is in the chain"); } return this.interceptors[this._index++]; } }; class GenericInterceptorChain { static { __name(this, "GenericInterceptorChain"); } context; /** * A getter for an array of interceptor functions or binding keys */ getInterceptors; // Implementation constructor(context, interceptors, comparator) { this.context = context; if (typeof interceptors === "function") { const interceptorsView = context.createView(interceptors, comparator); this.getInterceptors = () => { const bindings = interceptorsView.bindings; if (comparator) { bindings.sort(comparator); } return bindings.map((b) => b.key); }; } else if (Array.isArray(interceptors)) { this.getInterceptors = () => interceptors; } } /** * Invoke the interceptor chain */ invokeInterceptors(finalHandler) { const state = new InterceptorChainState(this.getInterceptors(), finalHandler); return this.next(state); } /** * Use the interceptor chain as an interceptor */ asInterceptor() { return (_ctx, next) => { return this.invokeInterceptors(next); }; } /** * Invoke downstream interceptors or the target method */ next(state) { if (state.done()) { return state.finalHandler(); } return this.invokeNextInterceptor(state); } /** * Invoke downstream interceptors */ invokeNextInterceptor(state) { const index = state.index; const interceptor = state.next(); const interceptorFn = this.loadInterceptor(interceptor); return transformValueOrPromise(interceptorFn, (fn) => { if (debug.enabled) { debug("Invoking interceptor %d (%s) on %s", index, fn.name); } return fn(this.context, () => this.next(state)); }); } /** * Return the interceptor function or resolve the interceptor function as a binding * from the context * * @param interceptor - Interceptor function or binding key */ loadInterceptor(interceptor) { if (typeof interceptor === "function") return interceptor; debug("Resolving interceptor binding %s", interceptor); return this.context.getValueOrPromise(interceptor); } } function invokeInterceptors(context, interceptors) { const chain = new GenericInterceptorChain(context, interceptors); return chain.invokeInterceptors(); } __name(invokeInterceptors, "invokeInterceptors"); function composeInterceptors(...interceptors) { return (ctx, next) => { const interceptor = new GenericInterceptorChain(ctx, interceptors).asInterceptor(); return interceptor(ctx, next); }; } __name(composeInterceptors, "composeInterceptors"); export { GenericInterceptorChain, composeInterceptors, invokeInterceptors }; //# sourceMappingURL=interceptor-chain.js.map