UNPKG

contexify

Version:

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

125 lines 4.61 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); import assert from "assert"; import { DecoratorFactory } from "metarize"; import { Context } from "../context/context.js"; import { resolveInjectedArguments } from "../resolution/resolver.js"; import createDebugger from "../utils/debug.js"; import { transformValueOrPromise } from "../utils/value-promise.js"; import { invokeMethodWithInterceptors } from "./interceptor.js"; const debug = createDebugger("contexify:invocation"); const getTargetName = DecoratorFactory.getTargetName; class InvocationContext extends Context { static { __name(this, "InvocationContext"); } target; methodName; args; source; /** * Construct a new instance of `InvocationContext` * @param parent - Parent context, such as the RequestContext * @param target - Target class (for static methods) or prototype/object * (for instance methods) * @param methodName - Method name * @param args - An array of arguments */ constructor(parent, target, methodName, args, source) { super(parent), this.target = target, this.methodName = methodName, this.args = args, this.source = source; } /** * The target class, such as `OrderController` */ get targetClass() { return typeof this.target === "function" ? this.target : this.target.constructor; } /** * The target name, such as `OrderController.prototype.cancelOrder` */ get targetName() { return getTargetName(this.target, this.methodName); } /** * Description of the invocation */ get description() { const source = this.source == null ? "" : `${this.source} => `; return `InvocationContext(${this.name}): ${source}${this.targetName}`; } toString() { return this.description; } /** * Assert the method exists on the target. An error will be thrown if otherwise. * @param context - Invocation context */ assertMethodExists() { const targetWithMethods = this.target; if (typeof targetWithMethods[this.methodName] !== "function") { const targetName = getTargetName(this.target, this.methodName); assert(false, `Method ${targetName} not found`); } return targetWithMethods; } /** * Invoke the target method with the given context * @param context - Invocation context * @param options - Options for the invocation */ invokeTargetMethod(options = { skipParameterInjection: true }) { const targetWithMethods = this.assertMethodExists(); if (!options.skipParameterInjection) { return invokeTargetMethodWithInjection(this, targetWithMethods, this.methodName, this.args, options.session); } return invokeTargetMethod(this, targetWithMethods, this.methodName, this.args); } } function invokeMethod(target, method, ctx, nonInjectedArgs = [], options = {}) { if (options.skipInterceptors) { if (options.skipParameterInjection) { return invokeTargetMethod(ctx, target, method, nonInjectedArgs); } return invokeTargetMethodWithInjection(ctx, target, method, nonInjectedArgs, options.session); } return invokeMethodWithInterceptors(ctx, target, method, nonInjectedArgs, options); } __name(invokeMethod, "invokeMethod"); function invokeTargetMethodWithInjection(ctx, target, method, nonInjectedArgs, session) { const methodName = getTargetName(target, method); if (debug.enabled) { debug("Invoking method %s", methodName); if (nonInjectedArgs?.length) { debug("Non-injected arguments:", nonInjectedArgs); } } const argsOrPromise = resolveInjectedArguments(target, method, ctx, session, nonInjectedArgs); const targetWithMethods = target; assert(typeof targetWithMethods[method] === "function", `Method ${method} not found`); return transformValueOrPromise(argsOrPromise, (args) => { if (debug.enabled) { debug("Injected arguments for %s:", methodName, args); } return invokeTargetMethod(ctx, targetWithMethods, method, args); }); } __name(invokeTargetMethodWithInjection, "invokeTargetMethodWithInjection"); function invokeTargetMethod(_ctx, target, methodName, args) { const targetWithMethods = target; if (debug.enabled) { debug("Invoking method %s", getTargetName(target, methodName), args); } const result = targetWithMethods[methodName](...args); if (debug.enabled) { debug("Method invoked: %s", getTargetName(target, methodName), result); } return result; } __name(invokeTargetMethod, "invokeTargetMethod"); export { InvocationContext, invokeMethod }; //# sourceMappingURL=invocation.js.map