( target: object, method: string, ctx: Context, session?: ResolutionSession, // eslint-disable-next-line @typescript-eslint/no-explicit-any nonInjectedArgs?: any[], )
| 180 | * @param nonInjectedArgs - Optional array of args for non-injected parameters |
| 181 | */ |
| 182 | export function resolveInjectedArguments( |
| 183 | target: object, |
| 184 | method: string, |
| 185 | ctx: Context, |
| 186 | session?: ResolutionSession, |
| 187 | // eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 188 | nonInjectedArgs?: any[], |
| 189 | ): ValueOrPromise<BoundValue[]> { |
| 190 | /* istanbul ignore if */ |
| 191 | if (debug.enabled) { |
| 192 | debug('Resolving injected arguments for %s', getTargetName(target, method)); |
| 193 | } |
| 194 | const targetWithMethods = <{[method: string]: Function}>target; |
| 195 | if (method) { |
| 196 | assert( |
| 197 | typeof targetWithMethods[method] === 'function', |
| 198 | `Method ${method} not found`, |
| 199 | ); |
| 200 | } |
| 201 | // NOTE: the array may be sparse, i.e. |
| 202 | // Object.keys(injectedArgs).length !== injectedArgs.length |
| 203 | // Example value: |
| 204 | // [ , 'key1', , 'key2'] |
| 205 | const injectedArgs = describeInjectedArguments(target, method); |
| 206 | const extraArgs = nonInjectedArgs ?? []; |
| 207 | |
| 208 | let argLength = DecoratorFactory.getNumberOfParameters(target, method); |
| 209 | |
| 210 | // Please note `injectedArgs` contains `undefined` for non-injected args |
| 211 | const numberOfInjected = injectedArgs.filter(i => i != null).length; |
| 212 | if (argLength < numberOfInjected + extraArgs.length) { |
| 213 | /** |
| 214 | * `Function.prototype.length` excludes the rest parameter and only includes |
| 215 | * parameters before the first one with a default value. For example, |
| 216 | * `hello(@inject('name') name: string = 'John')` gives 0 for argLength |
| 217 | */ |
| 218 | argLength = numberOfInjected + extraArgs.length; |
| 219 | } |
| 220 | |
| 221 | let nonInjectedIndex = 0; |
| 222 | return resolveList(new Array(argLength), (val, ix) => { |
| 223 | // The `val` argument is not used as the resolver only uses `injectedArgs` |
| 224 | // and `extraArgs` to return the new value |
| 225 | const injection = ix < injectedArgs.length ? injectedArgs[ix] : undefined; |
| 226 | if ( |
| 227 | injection == null || |
| 228 | (!injection.bindingSelector && !injection.resolve) |
| 229 | ) { |
| 230 | if (nonInjectedIndex < extraArgs.length) { |
| 231 | // Set the argument from the non-injected list |
| 232 | return extraArgs[nonInjectedIndex++]; |
| 233 | } else { |
| 234 | const name = getTargetName(target, method, ix); |
| 235 | throw new ResolutionError( |
| 236 | `The argument '${name}' is not decorated for dependency injection ` + |
| 237 | 'but no value was supplied by the caller. Did you forget to apply ' + |
| 238 | '@inject() to the argument?', |
| 239 | {context: ctx, options: {session}}, |
no test coverage detected