@tstdl/base 0.87.8 → 0.87.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38,7 +38,7 @@ function configureAuthenticationClient(config, injector = (0, import_inject.getC
38
38
  if ((0, import_type_guards.isDefined)(config.registerMiddleware)) {
39
39
  (injector ?? import_injector.Injector).register(import_tokens.HTTP_CLIENT_MIDDLEWARE, {
40
40
  useFactory(_, context) {
41
- const authenticationService = context.resolve(import_authentication_service.AuthenticationService);
41
+ const authenticationService = context.resolve(import_authentication_service.AuthenticationService, void 0, { forwardRef: true, forwardRefTypeHint: "object" });
42
42
  return (0, import_http_client_middleware.waitForAuthenticationCredentialsMiddleware)(authenticationService);
43
43
  }
44
44
  }, { multi: true });
@@ -2,6 +2,7 @@ import type { Decorator } from '../reflection/index.js';
2
2
  import type { Constructor, OneOrMany, Record, Simplify, TypedOmit } from '../types.js';
3
3
  import type { Provider } from './provider.js';
4
4
  import type { InjectionToken } from './token.js';
5
+ import type { InjectMetadata } from './type-info.js';
5
6
  import type { ArgumentProvider, ForwardRefInjectionToken, Mapper, RegistrationOptions } from './types.js';
6
7
  export type InjectDecorator = Decorator<'accessor' | 'constructorParameter'>;
7
8
  export type InjectableOptions<T, A, C extends Record = Record> = RegistrationOptions<T, A, C> & {
@@ -78,4 +79,4 @@ export declare function Optional(): InjectDecorator;
78
79
  * @param token token to resolve
79
80
  * @param argument resolve argument
80
81
  */
81
- export declare function ForwardRef<T extends object, A>(token: ForwardRefInjectionToken<T>, argument?: A): InjectDecorator;
82
+ export declare function ForwardRef<T extends object, A>(token?: ForwardRefInjectionToken<T>, argument?: A, options?: Pick<InjectMetadata, 'forwardRefTypeHint'>): InjectDecorator;
@@ -106,9 +106,10 @@ function ForwardArg(mapper = (value) => value) {
106
106
  function Optional() {
107
107
  return createInjectDecorator({ optional: true });
108
108
  }
109
- function ForwardRef(token, argument) {
109
+ function ForwardRef(token, argument, options) {
110
110
  const injectMetadata = {
111
- forwardRefToken: token
111
+ forwardRef: token ?? true,
112
+ forwardRefTypeHint: options?.forwardRefTypeHint
112
113
  };
113
114
  if ((0, import_type_guards.isDefined)(argument)) {
114
115
  injectMetadata.resolveArgumentProvider = () => argument;
@@ -2,22 +2,19 @@ import { Injector } from './injector.js';
2
2
  import type { Resolvable, ResolveArgument } from './interfaces.js';
3
3
  import type { InjectionToken } from './token.js';
4
4
  import type { ResolveOptions } from './types.js';
5
- export type InjectOptions = ResolveOptions & {
6
- /** if defined, resolve the ForwardRefToken using ForwardRef strategy instead resolving the token */
7
- forwardRef?: boolean;
8
- };
5
+ export type InjectOptions<T, A> = ResolveOptions<T, A>;
9
6
  export type InjectArgumentOptions = {
10
7
  optional?: boolean;
11
8
  };
12
9
  export type InjectionContext = {
13
10
  injector: Injector;
14
11
  argument: unknown;
15
- inject<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions): T;
16
- injectAll<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions): T[];
17
- injectAsync<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions): Promise<T>;
18
- injectAllAsync<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions): Promise<T[]>;
12
+ inject<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions<T, A>): T;
13
+ injectAll<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions<T, A>): T[];
14
+ injectAsync<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions<T, A>): Promise<T>;
15
+ injectAllAsync<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions<T, A>): Promise<T[]>;
19
16
  };
20
- export type InjectManyArrayItem<T, A> = [token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions];
17
+ export type InjectManyArrayItem<T, A> = [token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions<T, A>];
21
18
  export type InjectManyItem<T, A> = InjectionToken<T, A> | InjectManyArrayItem<T, A>;
22
19
  export type InjectManyItemReturnType<T extends InjectManyItem<any, any>> = T extends InjectManyItem<infer U, any> ? U | (T extends (InjectManyArrayItem<any, any> & [any, any, {
23
20
  optional: true;
@@ -32,10 +29,10 @@ export type InjectManyReturnType<T extends InjectManyItem<any, any>[]> = {
32
29
  * @param argument argument to resolve token with
33
30
  * @param options resolve options
34
31
  */
35
- export declare function inject<T = unknown, A = unknown>(token: InjectionToken<T, A>, argument: ResolveArgument<T, A>, options: InjectOptions & {
32
+ export declare function inject<T = unknown, A = unknown>(token: InjectionToken<T, A>, argument: ResolveArgument<T, A>, options: InjectOptions<T, A> & {
36
33
  optional: true;
37
34
  }): T | undefined;
38
- export declare function inject<T = unknown, A = unknown>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions & {
35
+ export declare function inject<T = unknown, A = unknown>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions<T, A> & {
39
36
  optional?: false;
40
37
  }): T;
41
38
  /**
@@ -51,10 +48,10 @@ export declare function injectMany<T extends InjectManyItem<any, any>[]>(...toke
51
48
  * @param argument argument to resolve token with
52
49
  * @param options resolve options
53
50
  */
54
- export declare function injectAsync<T = unknown, A = unknown>(token: InjectionToken<T, A>, argument: ResolveArgument<T, A>, options: InjectOptions & {
51
+ export declare function injectAsync<T = unknown, A = unknown>(token: InjectionToken<T, A>, argument: ResolveArgument<T, A>, options: InjectOptions<T, A> & {
55
52
  optional: true;
56
53
  }): Promise<T | undefined>;
57
- export declare function injectAsync<T = unknown, A = unknown>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions): Promise<T>;
54
+ export declare function injectAsync<T = unknown, A = unknown>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions<T, A>): Promise<T>;
58
55
  /**
59
56
  * Resolves tokens using the {@link Injector} of the current injection context
60
57
  *
@@ -68,7 +65,7 @@ export declare function injectManyAsync<T extends InjectManyItem<any, any>[]>(..
68
65
  * @param argument argument to resolve token with
69
66
  * @param options resolve options
70
67
  */
71
- export declare function injectAll<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions): T[];
68
+ export declare function injectAll<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions<T, A>): T[];
72
69
  /**
73
70
  * Resolves a token using the {@link Injector} of the current injection context
74
71
  *
@@ -76,7 +73,7 @@ export declare function injectAll<T, A>(token: InjectionToken<T, A>, argument?:
76
73
  * @param argument argument to resolve token with
77
74
  * @param options resolve options
78
75
  */
79
- export declare function injectAllAsync<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions): Promise<T[]>;
76
+ export declare function injectAllAsync<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: InjectOptions<T, A>): Promise<T[]>;
80
77
  /**
81
78
  * Injects the resolve argument from the current resolution
82
79
  * @param _this can be used for type infer by simply passing `this`. Requires class to implement {@link Resolvable}.
@@ -68,16 +68,16 @@ export declare class Injector implements AsyncDisposable {
68
68
  * @param token token to get registration for
69
69
  */
70
70
  getRegistration<T, A>(token: InjectionToken<T, A>, options?: GetRegistrationOptions): Registration<T, A> | Registration<T, A>[];
71
- resolve<T, A>(token: InjectionToken<T, A>, argument: ResolveArgument<T, A>, options: ResolveOptions & {
71
+ resolve<T, A>(token: InjectionToken<T, A>, argument: ResolveArgument<T, A>, options: ResolveOptions<T, A> & {
72
72
  optional: true;
73
73
  }): T | undefined;
74
- resolve<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: ResolveOptions): T;
75
- resolveAll<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: ResolveOptions): T[];
76
- resolveAsync<T, A>(token: InjectionToken<T, A>, argument: ResolveArgument<T, A>, options: ResolveOptions & {
74
+ resolve<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: ResolveOptions<T, A>): T;
75
+ resolveAll<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: ResolveOptions<T, A>): T[];
76
+ resolveAsync<T, A>(token: InjectionToken<T, A>, argument: ResolveArgument<T, A>, options: ResolveOptions<T, A> & {
77
77
  optional: true;
78
78
  }): Promise<T | undefined>;
79
- resolveAsync<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: ResolveOptions): Promise<T>;
80
- resolveAllAsync<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: ResolveOptions): Promise<T[]>;
79
+ resolveAsync<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: ResolveOptions<T, A>): Promise<T>;
80
+ resolveAllAsync<T, A>(token: InjectionToken<T, A>, argument?: ResolveArgument<T, A>, options?: ResolveOptions<T, A>): Promise<T[]>;
81
81
  private _resolve;
82
82
  private _resolveAll;
83
83
  private _resolveRegistration;
@@ -202,6 +202,14 @@ class Injector {
202
202
  }
203
203
  _resolve(token, argument, options, context, chain) {
204
204
  this.assertNotDisposed();
205
+ if ((0, import_type_guards.isDefined)(options.forwardRef) && options.forwardRef != false) {
206
+ (0, import_type_guards.assert)(options.optional != true, "ForwardRef does not support optional without resolveAll/injectAll as undefined is not forwardable.");
207
+ const forwardRef = import_forward_ref.ForwardRef.create();
208
+ const forwardToken = (0, import_type_guards.isFunction)(options.forwardRef) ? options.forwardRef() : token;
209
+ context.forwardRefQueue.add(() => import_forward_ref.ForwardRef.setRef(forwardRef, this._resolve(forwardToken, argument, { ...options, forwardRef: false }, context, chain.markAsForwardRef(forwardToken))));
210
+ context.forwardRefs.add(forwardRef);
211
+ return forwardRef;
212
+ }
205
213
  if ((0, import_type_guards.isUndefined)(token)) {
206
214
  throw new import_resolve_error.ResolveError("Token is undefined - this might be because of circular dependencies, use alias or forwardRef in this case.", chain);
207
215
  }
@@ -220,6 +228,13 @@ class Injector {
220
228
  }
221
229
  _resolveAll(token, argument, options, context, chain) {
222
230
  this.assertNotDisposed();
231
+ if ((0, import_type_guards.isDefined)(options.forwardRef) && options.forwardRef != false) {
232
+ const forwardRef = import_forward_ref.ForwardRef.create({ typeHint: options.forwardRefTypeHint });
233
+ const forwardToken = (0, import_type_guards.isFunction)(options.forwardRef) ? options.forwardRef() : token;
234
+ context.forwardRefQueue.add(() => import_forward_ref.ForwardRef.setRef(forwardRef, this._resolveAll(forwardToken, argument, { ...options, forwardRef: false }, context, chain.markAsForwardRef(forwardToken))));
235
+ context.forwardRefs.add(forwardRef);
236
+ return forwardRef;
237
+ }
223
238
  if ((0, import_type_guards.isUndefined)(token)) {
224
239
  throw new import_resolve_error.ResolveError("Token is undefined - this might be because of circular dependencies, use alias or forwardRef in this case.", chain);
225
240
  }
@@ -307,9 +322,9 @@ class Injector {
307
322
  result = { value: this._resolve(innerToken, arg, options, context, chain.addToken(innerToken)) };
308
323
  }
309
324
  if ((0, import_provider.isFactoryProvider)(provider)) {
325
+ const arg = resolveArgument ?? provider.defaultArgument ?? provider.defaultArgumentProvider?.();
326
+ injectionContext.argument = arg;
310
327
  try {
311
- const arg = resolveArgument ?? provider.defaultArgument ?? provider.defaultArgumentProvider?.();
312
- injectionContext.argument = arg;
313
328
  result = { value: provider.useFactory(arg, this.getResolveContext(resolutionTag, context, chain)) };
314
329
  } catch (error) {
315
330
  throw new import_resolve_error.ResolveError("Error in provider factory.", chain, error);
@@ -327,61 +342,39 @@ class Injector {
327
342
  }
328
343
  }
329
344
  resolveClassInjection(resolutionTag, context, constructor, metadata, resolveArgument, chain) {
330
- const getChain = (injectToken2) => chain.addParameter(constructor, metadata.index, injectToken2).addToken(injectToken2);
345
+ const getChain = (injectToken2) => chain.addParameter(constructor, metadata.index, injectToken2);
331
346
  const injectMetadata = metadata.data.tryGet(import_symbols.injectMetadataSymbol) ?? {};
332
347
  const injectToken = injectMetadata.injectToken ?? metadata.type;
333
348
  if ((0, import_type_guards.isDefined)(injectMetadata.injectArgumentMapper) && (!this.hasRegistration(injectToken) || (0, import_type_guards.isDefined)(resolveArgument) || (0, import_type_guards.isUndefined)(injectToken))) {
334
349
  return injectMetadata.injectArgumentMapper(resolveArgument);
335
350
  }
336
351
  const parameterResolveArgument = injectMetadata.forwardArgumentMapper?.(resolveArgument) ?? injectMetadata.resolveArgumentProvider?.(this.getResolveContext(resolutionTag, context, getChain(injectToken)));
337
- if ((0, import_type_guards.isDefined)(injectMetadata.forwardRefToken)) {
338
- const forwardRef = import_forward_ref.ForwardRef.create();
339
- const forwardRefToken = injectMetadata.forwardRefToken;
352
+ const forwardRef = injectMetadata.forwardRef;
353
+ if ((0, import_type_guards.isDefined)(forwardRef)) {
340
354
  context.forwardRefQueue.add(() => {
341
- const forwardToken = (0, import_type_guards.isFunction)(forwardRefToken) ? forwardRefToken() : forwardRefToken;
355
+ const forwardToken = (0, import_type_guards.isFunction)(forwardRef) ? forwardRef() : (0, import_type_guards.isBoolean)(forwardRef) ? injectToken : forwardRef;
342
356
  if ((0, import_type_guards.isDefined)(injectMetadata.mapper)) {
343
357
  throw new import_resolve_error.ResolveError("Cannot use inject mapper with forwardRef.", getChain(forwardToken));
344
358
  }
345
- const resolved2 = this[injectMetadata.resolveAll == true ? "_resolveAll" : "_resolve"](forwardToken, parameterResolveArgument, { optional: injectMetadata.optional }, context, getChain(forwardToken));
346
- import_forward_ref.ForwardRef.setRef(forwardRef, resolved2);
347
359
  });
348
- context.forwardRefs.add(forwardRef);
349
- return forwardRef;
350
360
  }
351
- const resolved = this._resolve(injectToken, parameterResolveArgument, { optional: injectMetadata.optional }, context, getChain(injectToken));
361
+ const resolveFn = injectMetadata.resolveAll == true ? "_resolveAll" : "_resolve";
362
+ const resolved = this[resolveFn](injectToken, parameterResolveArgument, { optional: injectMetadata.optional, forwardRef, forwardRefTypeHint: injectMetadata.forwardRefTypeHint }, context, getChain(injectToken));
352
363
  return (0, import_type_guards.isDefined)(injectMetadata.mapper) ? injectMetadata.mapper(resolved) : resolved;
353
364
  }
354
- resolveInjection(token, argument, options, context, chain) {
355
- if ((0, import_type_guards.isDefined)(options.forwardRef)) {
356
- const forwardRef = import_forward_ref.ForwardRef.create();
357
- context.forwardRefQueue.add(() => {
358
- const resolved = this._resolve(token, argument, options, context, chain.addToken(token));
359
- import_forward_ref.ForwardRef.setRef(forwardRef, resolved);
360
- });
361
- context.forwardRefs.add(forwardRef);
362
- return forwardRef;
363
- }
364
- return this._resolve(token, argument, options, context, chain.addToken(token));
365
+ resolveInjection(token, argument, options, context, injectIndex, chain) {
366
+ return this._resolve(token, argument, options, context, chain.addInject(token, injectIndex));
365
367
  }
366
- async resolveInjectionAsync(token, argument, options, context, chain) {
367
- const value = this.resolveInjection(token, argument, options, context, chain);
368
+ async resolveInjectionAsync(token, argument, options, context, injectIndex, chain) {
369
+ const value = this.resolveInjection(token, argument, options, context, injectIndex, chain);
368
370
  await context.$done;
369
371
  return value;
370
372
  }
371
- resolveInjectionAll(token, argument, options, context, chain) {
372
- if ((0, import_type_guards.isDefined)(options.forwardRef)) {
373
- const forwardRef = import_forward_ref.ForwardRef.create();
374
- context.forwardRefQueue.add(() => {
375
- const resolved = this._resolveAll(token, argument, options, context, chain.addToken(token));
376
- import_forward_ref.ForwardRef.setRef(forwardRef, resolved);
377
- });
378
- context.forwardRefs.add(forwardRef);
379
- return forwardRef;
380
- }
381
- return this._resolveAll(token, argument, options, context, chain.addToken(token));
373
+ resolveInjectionAll(token, argument, options, context, injectIndex, chain) {
374
+ return this._resolveAll(token, argument, options, context, chain.addInject(token, injectIndex));
382
375
  }
383
- async resolveInjectionAllAsync(token, argument, options, context, chain) {
384
- const values = this.resolveInjectionAll(token, argument, options, context, chain);
376
+ async resolveInjectionAllAsync(token, argument, options, context, injectIndex, chain) {
377
+ const values = this.resolveInjectionAll(token, argument, options, context, injectIndex, chain);
385
378
  await context.$done;
386
379
  return values;
387
380
  }
@@ -408,13 +401,14 @@ class Injector {
408
401
  return context;
409
402
  }
410
403
  getInjectionContext(resolveContext, resolveArgument, chain) {
404
+ let injectIndex = 0;
411
405
  const context = {
412
406
  injector: this,
413
407
  argument: resolveArgument,
414
- inject: (token, argument, options) => this.resolveInjection(token, argument, options ?? {}, resolveContext, chain),
415
- injectAll: (token, argument, options) => this.resolveInjectionAll(token, argument, options ?? {}, resolveContext, chain),
416
- injectAsync: async (token, argument, options) => this.resolveInjectionAsync(token, argument, options ?? {}, resolveContext, chain),
417
- injectAllAsync: async (token, argument, options) => this.resolveInjectionAllAsync(token, argument, options ?? {}, resolveContext, chain)
408
+ inject: (token, argument, options) => this.resolveInjection(token, argument, options ?? {}, resolveContext, injectIndex++, chain),
409
+ injectAll: (token, argument, options) => this.resolveInjectionAll(token, argument, options ?? {}, resolveContext, injectIndex++, chain),
410
+ injectAsync: async (token, argument, options) => this.resolveInjectionAsync(token, argument, options ?? {}, resolveContext, injectIndex++, chain),
411
+ injectAllAsync: async (token, argument, options) => this.resolveInjectionAllAsync(token, argument, options ?? {}, resolveContext, injectIndex++, chain)
418
412
  };
419
413
  return context;
420
414
  }
@@ -2,6 +2,7 @@ import type { AbstractConstructor } from '../types.js';
2
2
  import type { InjectionToken } from './token.js';
3
3
  export type ResolveChainNodeBase<Type extends string> = {
4
4
  type: Type;
5
+ forwardRef?: true;
5
6
  };
6
7
  export type ResolveChainNode = ResolveChainNodeBase<'token'> & {
7
8
  token: InjectionToken;
@@ -20,12 +21,14 @@ export type ResolveChainNode = ResolveChainNodeBase<'token'> & {
20
21
  export declare class ResolveChain {
21
22
  readonly nodes: readonly ResolveChainNode[];
22
23
  get length(): number;
23
- constructor(nodes?: ResolveChainNode[]);
24
+ /** @deprecated internal */
25
+ constructor(nodes: ResolveChainNode[]);
24
26
  static startWith(token: InjectionToken): ResolveChain;
25
27
  addToken(token: InjectionToken): ResolveChain;
26
28
  addInject(token: InjectionToken, index: number): ResolveChain;
27
29
  addParameter(constructor: AbstractConstructor, index: number, token: InjectionToken): ResolveChain;
28
30
  addProperty(constructor: AbstractConstructor, property: PropertyKey, token: InjectionToken): ResolveChain;
31
+ markAsForwardRef(forwardToken: InjectionToken): ResolveChain;
29
32
  format(truncate?: number): string;
30
33
  truncate(tokenCount: number): ResolveChain;
31
34
  }
@@ -29,11 +29,12 @@ class ResolveChain {
29
29
  get length() {
30
30
  return this.nodes.length;
31
31
  }
32
+ /** @deprecated internal */
32
33
  constructor(nodes) {
33
- this.nodes = nodes ?? [];
34
+ this.nodes = nodes;
34
35
  }
35
36
  static startWith(token) {
36
- const chain = new ResolveChain();
37
+ const chain = new ResolveChain([]);
37
38
  return chain.addToken(token);
38
39
  }
39
40
  addToken(token) {
@@ -52,6 +53,11 @@ class ResolveChain {
52
53
  const node = { type: "property", constructor, property, token };
53
54
  return new ResolveChain([...this.nodes, node]);
54
55
  }
56
+ markAsForwardRef(forwardToken) {
57
+ const nodes = [...this.nodes];
58
+ nodes.push({ ...nodes.pop(), token: forwardToken, forwardRef: true });
59
+ return new ResolveChain(nodes);
60
+ }
55
61
  format(truncate) {
56
62
  let chainString = "";
57
63
  const chain = (0, import_type_guards.isDefined)(truncate) ? this.truncate(truncate) : this;
@@ -60,26 +66,30 @@ class ResolveChain {
60
66
  }
61
67
  for (const node of chain.nodes) {
62
68
  const tokenName = (0, import_token.getTokenName)(node.token);
69
+ const forwardRefPrefix = node.forwardRef ? "ForwardRef::" : "";
63
70
  switch (node.type) {
64
71
  case "token":
65
72
  chainString += `
66
- -> ${tokenName}`;
73
+ -> ${forwardRefPrefix}${tokenName}`;
67
74
  break;
68
75
  case "inject":
76
+ chainString += ` => inject(${forwardRefPrefix}${tokenName}) [${node.index + 1}]`;
69
77
  chainString += `
70
- -> inject(${tokenName}) #${node.index + 1}`;
78
+ -> ${tokenName}`;
71
79
  break;
72
80
  case "parameter":
73
81
  const metadata = import_reflection.reflectionRegistry.getMetadata(node.constructor);
74
82
  const prefix = "_, ".repeat(node.index);
75
- const suffix = ", _".repeat((0, import_type_guards.assertDefinedPass)(metadata?.parameters, "missing parameters metadata").length - node.index - 1);
76
- chainString += `(${prefix}${tokenName}${suffix})`;
83
+ const suffix = ", _".repeat((0, import_type_guards.assertDefinedPass)(metadata?.parameters, `missing parameters metadata for ${node.constructor.name}`).length - node.index - 1);
84
+ chainString += `(${prefix}${forwardRefPrefix}${tokenName}${suffix})`;
85
+ chainString += `
86
+ -> ${tokenName}`;
77
87
  break;
78
88
  case "property":
79
89
  const constructorName = (0, import_token.getTokenName)(node.constructor);
80
90
  const key = getPropertyKeyString(node.property);
81
91
  chainString += `
82
- -> ${constructorName}[${key}]: ${tokenName}`;
92
+ -> ${constructorName}[${key}]: ${forwardRefPrefix}${tokenName}`;
83
93
  break;
84
94
  default:
85
95
  throw new Error(`unknown chain node type ${node.type}`);
@@ -26,11 +26,12 @@ var import_type_guards = require("../utils/type-guards.js");
26
26
  class ResolveError extends import_custom_error.CustomError {
27
27
  constructor(message, chain, cause) {
28
28
  const causeMessage = (0, import_type_guards.isDefined)(cause) ? `
29
- cause: ${cause.message}` : "";
29
+ cause: ${cause?.message}` : "";
30
30
  super({
31
31
  message: `${message}${causeMessage}
32
32
  chain: ${chain.format(15)}`,
33
- cause
33
+ cause,
34
+ stack: cause?.stack
34
35
  });
35
36
  }
36
37
  }
@@ -1,10 +1,12 @@
1
+ import type { ForwardRefTypeHint } from '../utils/object/forward-ref.js';
1
2
  import type { InjectionToken } from './token.js';
2
3
  import type { ArgumentProvider, ForwardRefInjectionToken, Mapper } from './types.js';
3
4
  export type InjectMetadata = {
4
5
  /** token overwrite by inject decorator */
5
6
  injectToken?: InjectionToken;
6
- /** if defined, resolve the ForwardRefToken using ForwardRef strategy instead resolving the token */
7
- forwardRefToken?: ForwardRefInjectionToken;
7
+ /** if defined, resolve the token or ForwardRefToken using ForwardRef strategy instead of resolving the token directly */
8
+ forwardRef?: boolean | ForwardRefInjectionToken;
9
+ forwardRefTypeHint?: ForwardRefTypeHint;
8
10
  /** whether injection is optional if token is not registered. Set by optional decorator */
9
11
  optional?: boolean;
10
12
  /** whether injection should resolve all providers */
@@ -1,6 +1,7 @@
1
1
  import type { CancellationSignal } from '../cancellation/index.js';
2
2
  import type { AsyncDisposeHandler } from '../disposable/async-disposer.js';
3
3
  import type { Record } from '../types.js';
4
+ import type { ForwardRefTypeHint } from '../utils/object/forward-ref.js';
4
5
  import type { Injector } from './injector.js';
5
6
  import type { ResolveArgument } from './interfaces.js';
6
7
  import type { InjectionToken } from './token.js';
@@ -24,10 +25,13 @@ export type AfterResolveContext<D extends Record> = {
24
25
  export type Mapper<T = any, U = unknown> = (value: T) => U;
25
26
  export type ArgumentProvider<T = unknown, D extends Record = Record> = (context: ResolveContext<D>) => T;
26
27
  export type ForwardRefInjectionToken<T = any, A = any> = Exclude<InjectionToken<T, A>, Function> | (() => InjectionToken<T, A>);
27
- export type ResolveOptions = {
28
+ export type ResolveOptions<T, A> = {
28
29
  optional?: boolean;
29
30
  skipSelf?: boolean;
30
31
  onlySelf?: boolean;
32
+ /** If defined, resolve the token using ForwardRef strategy instead of resolving the token directly can be used to circumvent circular dependency problems */
33
+ forwardRef?: boolean | ForwardRefInjectionToken<T, A>;
34
+ forwardRefTypeHint?: ForwardRefTypeHint;
31
35
  };
32
36
  /**
33
37
  * data to store between different stages like resolve and afterResolve
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.87.8",
3
+ "version": "0.87.10",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -1,7 +1,10 @@
1
1
  declare const isForwardRef: unique symbol;
2
+ export type ForwardRefTypeHint = 'object' | 'function';
2
3
  export type ForwardRefOptions<T extends object = object> = {
3
4
  reference?: T;
4
5
  initializer?: () => T;
6
+ /** Due to limitations of Proxy, there can be some issues if proxy is created with a target of the "wrong" type. If possible, you should specify the type is forward ref is going to forward to. */
7
+ typeHint?: ForwardRefTypeHint;
5
8
  };
6
9
  export type ForwardRef<T extends object = object> = T & {
7
10
  [isForwardRef]: true;
@@ -54,8 +54,8 @@ const ForwardRef = {
54
54
  }
55
55
  };
56
56
  function getForwardRefProxy(context) {
57
- function forwardRef() {
58
- }
57
+ const target = context.typeHint == "function" ? function forwardRef() {
58
+ } : { forwardRef: true };
59
59
  const handler = {};
60
60
  for (const method of import_proxy.reflectMethods) {
61
61
  handler[method] = {
@@ -68,7 +68,7 @@ function getForwardRefProxy(context) {
68
68
  }
69
69
  }[method];
70
70
  }
71
- return new Proxy(forwardRef, handler);
71
+ return new Proxy(target, handler);
72
72
  }
73
73
  function getContext(options) {
74
74
  const reference = (0, import_type_guards.isDefined)(options?.reference) ? { value: options?.reference } : (0, import_type_guards.isDefined)(options?.initializer) ? { initializer: options?.initializer } : { value: void 0 };