UNPKG

6.65 kBJavaScriptView Raw
1"use strict";
2// Copyright IBM Corp. and LoopBack contributors 2019,2020. All Rights Reserved.
3// Node module: @loopback/context
4// This file is licensed under the MIT License.
5// License text available at https://opensource.org/licenses/MIT
6Object.defineProperty(exports, "__esModule", { value: true });
7exports.invokeMethod = exports.InvocationContext = void 0;
8const tslib_1 = require("tslib");
9const metadata_1 = require("@loopback/metadata");
10const assert_1 = tslib_1.__importDefault(require("assert"));
11const debug_1 = tslib_1.__importDefault(require("debug"));
12const context_1 = require("./context");
13const interceptor_1 = require("./interceptor");
14const resolver_1 = require("./resolver");
15const value_promise_1 = require("./value-promise");
16const debug = (0, debug_1.default)('loopback:context:invocation');
17const getTargetName = metadata_1.DecoratorFactory.getTargetName;
18/**
19 * InvocationContext represents the context to invoke interceptors for a method.
20 * The context can be used to access metadata about the invocation as well as
21 * other dependencies.
22 */
23class InvocationContext extends context_1.Context {
24 /**
25 * Construct a new instance of `InvocationContext`
26 * @param parent - Parent context, such as the RequestContext
27 * @param target - Target class (for static methods) or prototype/object
28 * (for instance methods)
29 * @param methodName - Method name
30 * @param args - An array of arguments
31 */
32 constructor(parent, target, methodName, args, source) {
33 super(parent);
34 this.target = target;
35 this.methodName = methodName;
36 this.args = args;
37 this.source = source;
38 }
39 /**
40 * The target class, such as `OrderController`
41 */
42 get targetClass() {
43 return typeof this.target === 'function'
44 ? this.target
45 : this.target.constructor;
46 }
47 /**
48 * The target name, such as `OrderController.prototype.cancelOrder`
49 */
50 get targetName() {
51 return getTargetName(this.target, this.methodName);
52 }
53 /**
54 * Description of the invocation
55 */
56 get description() {
57 const source = this.source == null ? '' : `${this.source} => `;
58 return `InvocationContext(${this.name}): ${source}${this.targetName}`;
59 }
60 toString() {
61 return this.description;
62 }
63 /**
64 * Assert the method exists on the target. An error will be thrown if otherwise.
65 * @param context - Invocation context
66 */
67 assertMethodExists() {
68 const targetWithMethods = this.target;
69 if (typeof targetWithMethods[this.methodName] !== 'function') {
70 const targetName = getTargetName(this.target, this.methodName);
71 (0, assert_1.default)(false, `Method ${targetName} not found`);
72 }
73 return targetWithMethods;
74 }
75 /**
76 * Invoke the target method with the given context
77 * @param context - Invocation context
78 * @param options - Options for the invocation
79 */
80 invokeTargetMethod(options = { skipParameterInjection: true }) {
81 const targetWithMethods = this.assertMethodExists();
82 if (!options.skipParameterInjection) {
83 return invokeTargetMethodWithInjection(this, targetWithMethods, this.methodName, this.args, options.session);
84 }
85 return invokeTargetMethod(this, targetWithMethods, this.methodName, this.args);
86 }
87}
88exports.InvocationContext = InvocationContext;
89/**
90 * Invoke a method using dependency injection. Interceptors are invoked as part
91 * of the invocation.
92 * @param target - Target of the method, it will be the class for a static
93 * method, and instance or class prototype for a prototype method
94 * @param method - Name of the method
95 * @param ctx - Context object
96 * @param nonInjectedArgs - Optional array of args for non-injected parameters
97 * @param options - Options for the invocation
98 */
99function invokeMethod(target, method, ctx, nonInjectedArgs = [], options = {}) {
100 if (options.skipInterceptors) {
101 if (options.skipParameterInjection) {
102 // Invoke the target method directly without injection or interception
103 return invokeTargetMethod(ctx, target, method, nonInjectedArgs);
104 }
105 else {
106 return invokeTargetMethodWithInjection(ctx, target, method, nonInjectedArgs, options.session);
107 }
108 }
109 // Invoke the target method with interception but no injection
110 return (0, interceptor_1.invokeMethodWithInterceptors)(ctx, target, method, nonInjectedArgs, options);
111}
112exports.invokeMethod = invokeMethod;
113/**
114 * Invoke a method. Method parameter dependency injection is honored.
115 * @param target - Target of the method, it will be the class for a static
116 * method, and instance or class prototype for a prototype method
117 * @param method - Name of the method
118 * @param ctx - Context
119 * @param nonInjectedArgs - Optional array of args for non-injected parameters
120 */
121function invokeTargetMethodWithInjection(ctx, target, method, nonInjectedArgs, session) {
122 const methodName = getTargetName(target, method);
123 /* istanbul ignore if */
124 if (debug.enabled) {
125 debug('Invoking method %s', methodName);
126 if (nonInjectedArgs === null || nonInjectedArgs === void 0 ? void 0 : nonInjectedArgs.length) {
127 debug('Non-injected arguments:', nonInjectedArgs);
128 }
129 }
130 const argsOrPromise = (0, resolver_1.resolveInjectedArguments)(target, method, ctx, session, nonInjectedArgs);
131 const targetWithMethods = target;
132 (0, assert_1.default)(typeof targetWithMethods[method] === 'function', `Method ${method} not found`);
133 return (0, value_promise_1.transformValueOrPromise)(argsOrPromise, args => {
134 /* istanbul ignore if */
135 if (debug.enabled) {
136 debug('Injected arguments for %s:', methodName, args);
137 }
138 return invokeTargetMethod(ctx, targetWithMethods, method, args);
139 });
140}
141/**
142 * Invoke the target method
143 * @param ctx - Context object
144 * @param target - Target class or object
145 * @param methodName - Target method name
146 * @param args - Arguments
147 */
148function invokeTargetMethod(ctx, // Not used
149target, methodName, args) {
150 const targetWithMethods = target;
151 /* istanbul ignore if */
152 if (debug.enabled) {
153 debug('Invoking method %s', getTargetName(target, methodName), args);
154 }
155 // Invoke the target method
156 const result = targetWithMethods[methodName](...args);
157 /* istanbul ignore if */
158 if (debug.enabled) {
159 debug('Method invoked: %s', getTargetName(target, methodName), result);
160 }
161 return result;
162}
163//# sourceMappingURL=invocation.js.map
\No newline at end of file