1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | Object.defineProperty(exports, "__esModule", { value: true });
|
7 | exports.resolveInjectedProperties = exports.resolveInjectedArguments = exports.instantiateClass = void 0;
|
8 | const tslib_1 = require("tslib");
|
9 | const metadata_1 = require("@loopback/metadata");
|
10 | const assert_1 = tslib_1.__importDefault(require("assert"));
|
11 | const debug_1 = tslib_1.__importDefault(require("debug"));
|
12 | const binding_filter_1 = require("./binding-filter");
|
13 | const inject_1 = require("./inject");
|
14 | const resolution_session_1 = require("./resolution-session");
|
15 | const value_promise_1 = require("./value-promise");
|
16 | const debug = (0, debug_1.default)('loopback:context:resolver');
|
17 | const getTargetName = metadata_1.DecoratorFactory.getTargetName;
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | function instantiateClass(ctor, ctx, session,
|
31 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
32 | nonInjectedArgs) {
|
33 |
|
34 | if (debug.enabled) {
|
35 | debug('Instantiating %s', getTargetName(ctor));
|
36 | if (nonInjectedArgs === null || nonInjectedArgs === void 0 ? void 0 : nonInjectedArgs.length) {
|
37 | debug('Non-injected arguments:', nonInjectedArgs);
|
38 | }
|
39 | }
|
40 | const argsOrPromise = resolveInjectedArguments(ctor, '', ctx, session, nonInjectedArgs);
|
41 | const propertiesOrPromise = resolveInjectedProperties(ctor, ctx, session);
|
42 | const inst = (0, value_promise_1.transformValueOrPromise)(argsOrPromise, args => {
|
43 |
|
44 | if (debug.enabled) {
|
45 | debug('Injected arguments for %s():', ctor.name, args);
|
46 | }
|
47 | return new ctor(...args);
|
48 | });
|
49 | return (0, value_promise_1.transformValueOrPromise)(propertiesOrPromise, props => {
|
50 |
|
51 | if (debug.enabled) {
|
52 | debug('Injected properties for %s:', ctor.name, props);
|
53 | }
|
54 | return (0, value_promise_1.transformValueOrPromise)(inst, obj => Object.assign(obj, props));
|
55 | });
|
56 | }
|
57 | exports.instantiateClass = instantiateClass;
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | function resolveContext(ctx, injection, session) {
|
65 | const currentBinding = session === null || session === void 0 ? void 0 : session.currentBinding;
|
66 | if (currentBinding == null) {
|
67 |
|
68 | return ctx;
|
69 | }
|
70 | const isConstructorOrPropertyInjection =
|
71 |
|
72 | !injection.member ||
|
73 |
|
74 | typeof injection.methodDescriptorOrParameterIndex !== 'number';
|
75 | if (isConstructorOrPropertyInjection) {
|
76 |
|
77 |
|
78 | ctx = ctx.getResolutionContext(currentBinding);
|
79 | }
|
80 | return ctx;
|
81 | }
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | function resolve(ctx, injection, session) {
|
89 |
|
90 | if (debug.enabled) {
|
91 | debug('Resolving an injection:', resolution_session_1.ResolutionSession.describeInjection(injection));
|
92 | }
|
93 | ctx = resolveContext(ctx, injection, session);
|
94 | const resolved = resolution_session_1.ResolutionSession.runWithInjection(s => {
|
95 | if (injection.resolve) {
|
96 |
|
97 | return injection.resolve(ctx, injection, s);
|
98 | }
|
99 | else {
|
100 |
|
101 | (0, assert_1.default)((0, binding_filter_1.isBindingAddress)(injection.bindingSelector), 'The binding selector must be an address (string or BindingKey)');
|
102 | const key = injection.bindingSelector;
|
103 | const options = {
|
104 | session: s,
|
105 | ...injection.metadata,
|
106 | };
|
107 | return ctx.getValueOrPromise(key, options);
|
108 | }
|
109 | }, injection, session);
|
110 | return resolved;
|
111 | }
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 | function resolveInjectedArguments(target, method, ctx, session,
|
129 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
130 | nonInjectedArgs) {
|
131 |
|
132 | if (debug.enabled) {
|
133 | debug('Resolving injected arguments for %s', getTargetName(target, method));
|
134 | }
|
135 | const targetWithMethods = target;
|
136 | if (method) {
|
137 | (0, assert_1.default)(typeof targetWithMethods[method] === 'function', `Method ${method} not found`);
|
138 | }
|
139 |
|
140 |
|
141 |
|
142 |
|
143 | const injectedArgs = (0, inject_1.describeInjectedArguments)(target, method);
|
144 | const extraArgs = nonInjectedArgs !== null && nonInjectedArgs !== void 0 ? nonInjectedArgs : [];
|
145 | let argLength = metadata_1.DecoratorFactory.getNumberOfParameters(target, method);
|
146 |
|
147 | const numberOfInjected = injectedArgs.filter(i => i != null).length;
|
148 | if (argLength < numberOfInjected + extraArgs.length) {
|
149 | |
150 |
|
151 |
|
152 |
|
153 |
|
154 | argLength = numberOfInjected + extraArgs.length;
|
155 | }
|
156 | let nonInjectedIndex = 0;
|
157 | return (0, value_promise_1.resolveList)(new Array(argLength), (val, ix) => {
|
158 |
|
159 |
|
160 | const injection = ix < injectedArgs.length ? injectedArgs[ix] : undefined;
|
161 | if (injection == null ||
|
162 | (!injection.bindingSelector && !injection.resolve)) {
|
163 | if (nonInjectedIndex < extraArgs.length) {
|
164 |
|
165 | return extraArgs[nonInjectedIndex++];
|
166 | }
|
167 | else {
|
168 | const name = getTargetName(target, method, ix);
|
169 | throw new resolution_session_1.ResolutionError(`The argument '${name}' is not decorated for dependency injection ` +
|
170 | 'but no value was supplied by the caller. Did you forget to apply ' +
|
171 | '@inject() to the argument?', { context: ctx, options: { session } });
|
172 | }
|
173 | }
|
174 | return resolve(ctx, injection,
|
175 |
|
176 | resolution_session_1.ResolutionSession.fork(session));
|
177 | });
|
178 | }
|
179 | exports.resolveInjectedArguments = resolveInjectedArguments;
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 | function resolveInjectedProperties(constructor, ctx, session) {
|
193 |
|
194 | if (debug.enabled) {
|
195 | debug('Resolving injected properties for %s', getTargetName(constructor));
|
196 | }
|
197 | const injectedProperties = (0, inject_1.describeInjectedProperties)(constructor.prototype);
|
198 | return (0, value_promise_1.resolveMap)(injectedProperties, injection => resolve(ctx, injection,
|
199 | // Clone the session so that multiple properties can be resolved in parallel
|
200 | resolution_session_1.ResolutionSession.fork(session)));
|
201 | }
|
202 | exports.resolveInjectedProperties = resolveInjectedProperties;
|
203 | //# sourceMappingURL=resolver.js.map |
\ | No newline at end of file |