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
JavaScript
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