@zudojs/container 0.1.0 → 1.1.0

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.
Files changed (86) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +221 -8
  3. package/dist/containerCore/containerCore.core.d.ts +112 -14
  4. package/dist/containerCore/containerCore.core.js +228 -46
  5. package/dist/containerCore/containerCore.scope.d.ts +66 -18
  6. package/dist/containerCore/containerCore.scope.js +120 -31
  7. package/dist/containerCore/containerCore.type.d.ts +22 -16
  8. package/dist/containerLifecycle/containerLifecycle.core.d.ts +59 -9
  9. package/dist/containerLifecycle/containerLifecycle.core.js +60 -15
  10. package/dist/containerOptions/containerOptions.type.d.ts +7 -17
  11. package/dist/containerOptions/containerOptions.type.js +0 -19
  12. package/dist/containerProvider/containerProvider.core.d.ts +11 -3
  13. package/dist/containerProvider/containerProvider.core.js +11 -5
  14. package/dist/containerRegistration/containerRegistration.core.d.ts +9 -3
  15. package/dist/containerRegistration/containerRegistration.core.js +0 -6
  16. package/dist/containerRegistry/containerRegistry.core.d.ts +23 -9
  17. package/dist/containerRegistry/containerRegistry.core.js +50 -47
  18. package/dist/containerRegistry/containerRegistry.type.d.ts +3 -1
  19. package/dist/containerRegistry/containerRegistry.type.js +2 -0
  20. package/dist/containerRegistry/index.d.ts +0 -1
  21. package/dist/containerRegistry/index.js +0 -1
  22. package/dist/containerResolution/containerResolution.core.d.ts +51 -10
  23. package/dist/containerResolution/containerResolution.core.js +255 -64
  24. package/dist/containerResolution/containerResolution.error.d.ts +68 -3
  25. package/dist/containerResolution/containerResolution.error.js +107 -3
  26. package/dist/containerResolution/containerResolution.type.d.ts +35 -3
  27. package/dist/containerResolution/index.d.ts +1 -0
  28. package/dist/containerResolution/index.js +1 -0
  29. package/dist/containerToken/containerToken.type.d.ts +26 -1
  30. package/dist/containerToken/containerToken.type.js +18 -0
  31. package/dist/index.d.ts +1 -0
  32. package/dist/index.js +3 -0
  33. package/package.json +25 -12
  34. package/dist/.tsbuildinfo +0 -1
  35. package/dist/containerCore/containerCore.core.d.ts.map +0 -1
  36. package/dist/containerCore/containerCore.core.js.map +0 -1
  37. package/dist/containerCore/containerCore.scope.d.ts.map +0 -1
  38. package/dist/containerCore/containerCore.scope.js.map +0 -1
  39. package/dist/containerCore/containerCore.type.d.ts.map +0 -1
  40. package/dist/containerCore/containerCore.type.js.map +0 -1
  41. package/dist/containerCore/index.d.ts.map +0 -1
  42. package/dist/containerCore/index.js.map +0 -1
  43. package/dist/containerLifecycle/containerLifecycle.core.d.ts.map +0 -1
  44. package/dist/containerLifecycle/containerLifecycle.core.js.map +0 -1
  45. package/dist/containerLifecycle/index.d.ts.map +0 -1
  46. package/dist/containerLifecycle/index.js.map +0 -1
  47. package/dist/containerOptions/containerOptions.type.d.ts.map +0 -1
  48. package/dist/containerOptions/containerOptions.type.js.map +0 -1
  49. package/dist/containerOptions/index.d.ts.map +0 -1
  50. package/dist/containerOptions/index.js.map +0 -1
  51. package/dist/containerProvider/containerProvider.core.d.ts.map +0 -1
  52. package/dist/containerProvider/containerProvider.core.js.map +0 -1
  53. package/dist/containerProvider/index.d.ts.map +0 -1
  54. package/dist/containerProvider/index.js.map +0 -1
  55. package/dist/containerRegistration/containerRegistration.core.d.ts.map +0 -1
  56. package/dist/containerRegistration/containerRegistration.core.js.map +0 -1
  57. package/dist/containerRegistration/index.d.ts.map +0 -1
  58. package/dist/containerRegistration/index.js.map +0 -1
  59. package/dist/containerRegistry/containerRegistry.core.d.ts.map +0 -1
  60. package/dist/containerRegistry/containerRegistry.core.js.map +0 -1
  61. package/dist/containerRegistry/containerRegistry.error.d.ts +0 -12
  62. package/dist/containerRegistry/containerRegistry.error.d.ts.map +0 -1
  63. package/dist/containerRegistry/containerRegistry.error.js +0 -22
  64. package/dist/containerRegistry/containerRegistry.error.js.map +0 -1
  65. package/dist/containerRegistry/containerRegistry.type.d.ts.map +0 -1
  66. package/dist/containerRegistry/containerRegistry.type.js.map +0 -1
  67. package/dist/containerRegistry/index.d.ts.map +0 -1
  68. package/dist/containerRegistry/index.js.map +0 -1
  69. package/dist/containerResolution/containerResolution.core.d.ts.map +0 -1
  70. package/dist/containerResolution/containerResolution.core.js.map +0 -1
  71. package/dist/containerResolution/containerResolution.error.d.ts.map +0 -1
  72. package/dist/containerResolution/containerResolution.error.js.map +0 -1
  73. package/dist/containerResolution/containerResolution.type.d.ts.map +0 -1
  74. package/dist/containerResolution/containerResolution.type.js.map +0 -1
  75. package/dist/containerResolution/index.d.ts.map +0 -1
  76. package/dist/containerResolution/index.js.map +0 -1
  77. package/dist/containerScope/containerScope.type.d.ts.map +0 -1
  78. package/dist/containerScope/containerScope.type.js.map +0 -1
  79. package/dist/containerScope/index.d.ts.map +0 -1
  80. package/dist/containerScope/index.js.map +0 -1
  81. package/dist/containerToken/containerToken.type.d.ts.map +0 -1
  82. package/dist/containerToken/containerToken.type.js.map +0 -1
  83. package/dist/containerToken/index.d.ts.map +0 -1
  84. package/dist/containerToken/index.js.map +0 -1
  85. package/dist/index.d.ts.map +0 -1
  86. package/dist/index.js.map +0 -1
@@ -18,10 +18,12 @@ export function isTokenProvider(provider) {
18
18
  return "provide" in provider && "provider" in provider;
19
19
  }
20
20
  export function hasInjectedDependencies(provider) {
21
- return isFactoryProvider(provider) && Array.isArray(provider.inject);
21
+ return ((isFactoryProvider(provider) || isClassProvider(provider)) &&
22
+ Array.isArray(provider.inject) &&
23
+ provider.inject.length > 0);
22
24
  }
23
- export function classProvider(useClass) {
24
- return Object.freeze({ useClass });
25
+ export function classProvider(useClass, inject = []) {
26
+ return Object.freeze({ useClass, inject: Object.freeze([...inject]) });
25
27
  }
26
28
  export function factoryProvider(useFactory, inject = []) {
27
29
  return Object.freeze({ useFactory, inject: Object.freeze([...inject]) });
@@ -32,8 +34,12 @@ export function valueProvider(useValue) {
32
34
  export function existingProvider(useExisting) {
33
35
  return Object.freeze({ useExisting });
34
36
  }
35
- export function provideClass(provide, useClass) {
36
- return Object.freeze({ provide, useClass });
37
+ export function provideClass(provide, useClass, inject = []) {
38
+ return Object.freeze({
39
+ provide,
40
+ useClass,
41
+ inject: Object.freeze([...inject]),
42
+ });
37
43
  }
38
44
  export function provideFactory(provide, useFactory, inject = []) {
39
45
  return Object.freeze({
@@ -6,6 +6,15 @@ import { ContainerScope } from "../containerScope/containerScope.type.js";
6
6
  import type { ContainerProvider, ProviderToken } from "../containerProvider/containerProvider.core.js";
7
7
  import type { InjectionToken, Token } from "../containerToken/containerToken.type.js";
8
8
  export type RegistrationToken<T = unknown> = Token<T> | InjectionToken<T>;
9
+ /** The type a registration token resolves to (`unknown` for untyped tokens). */
10
+ export type ResolvedToken<T extends RegistrationToken> = T extends RegistrationToken<infer U> ? U : never;
11
+ /**
12
+ * Maps a tuple of registration tokens to a tuple of their resolved types, so
13
+ * `resolveMany([LOGGER, DB])` is typed `[Logger, Db]`.
14
+ */
15
+ export type ResolvedTokens<Tokens extends readonly RegistrationToken[]> = {
16
+ -readonly [K in keyof Tokens]: Tokens[K] extends RegistrationToken ? ResolvedToken<Tokens[K]> : never;
17
+ };
9
18
  export interface RegistrationMetadata {
10
19
  readonly name?: string;
11
20
  readonly description?: string;
@@ -18,7 +27,6 @@ export interface ContainerRegistration<T = unknown> {
18
27
  readonly provider: ContainerProvider<T>;
19
28
  readonly scope: ContainerScope;
20
29
  readonly metadata: RegistrationMetadata;
21
- readonly initialized: boolean;
22
30
  readonly createdAt: Date;
23
31
  }
24
32
  export interface CreateRegistrationOptions extends RegistrationMetadata {
@@ -29,13 +37,11 @@ export interface MutableRegistrationState<T = unknown> {
29
37
  readonly provider: ContainerProvider<T>;
30
38
  scope: ContainerScope;
31
39
  metadata: RegistrationMetadata;
32
- initialized: boolean;
33
40
  createdAt: Date;
34
41
  }
35
42
  export declare function createRegistration<T>(token: RegistrationToken<T>, provider: ContainerProvider<T>, options?: CreateRegistrationOptions): ContainerRegistration<T>;
36
43
  export declare function createMutableRegistrationState<T>(registration: ContainerRegistration<T>): MutableRegistrationState<T>;
37
44
  export declare function freezeRegistration<T>(state: MutableRegistrationState<T>): ContainerRegistration<T>;
38
- export declare function markRegistrationInitialized<T>(registration: ContainerRegistration<T>): ContainerRegistration<T>;
39
45
  export declare function getRegistrationToken<T>(registration: ContainerRegistration<T>): Token<T>;
40
46
  export declare function getRegistrationProviderToken<T>(registration: ContainerRegistration<T>): ProviderToken<T> | undefined;
41
47
  export declare function isSingletonRegistration<T>(registration: ContainerRegistration<T>): boolean;
@@ -13,7 +13,6 @@ export function createRegistration(token, provider, options = {}) {
13
13
  provider: normalizedProvider,
14
14
  scope: resolveContainerScope(options.scope),
15
15
  metadata: createRegistrationMetadata(options, normalizedToken),
16
- initialized: false,
17
16
  createdAt: new Date(),
18
17
  };
19
18
  return Object.freeze({
@@ -43,7 +42,6 @@ export function createMutableRegistrationState(registration) {
43
42
  provider: registration.provider,
44
43
  scope: registration.scope,
45
44
  metadata: registration.metadata,
46
- initialized: registration.initialized,
47
45
  createdAt: registration.createdAt,
48
46
  };
49
47
  }
@@ -58,13 +56,9 @@ export function freezeRegistration(state) {
58
56
  ? Object.freeze({ ...state.metadata.metadata })
59
57
  : undefined,
60
58
  }),
61
- initialized: state.initialized,
62
59
  createdAt: state.createdAt,
63
60
  });
64
61
  }
65
- export function markRegistrationInitialized(registration) {
66
- return Object.freeze({ ...registration, initialized: true });
67
- }
68
62
  export function getRegistrationToken(registration) {
69
63
  return unwrapToken(registration.token);
70
64
  }
@@ -1,9 +1,12 @@
1
1
  /**
2
2
  * Container registration registry.
3
+ *
4
+ * The registry stores normalized registrations and emits change events
5
+ * (REGISTER / REPLACE / REMOVE / CLEAR / RESTORE) so collaborators — notably
6
+ * the resolver's singleton cache — can react to mutations.
3
7
  */
4
8
  import type { ContainerProvider } from "../containerProvider/containerProvider.core.js";
5
- import type { ContainerScope } from "../containerScope/containerScope.type.js";
6
- import type { ContainerRegistration, CreateRegistrationOptions, RegistrationMetadata, RegistrationToken } from "../containerRegistration/containerRegistration.core.js";
9
+ import type { ContainerRegistration, CreateRegistrationOptions, RegistrationToken } from "../containerRegistration/containerRegistration.core.js";
7
10
  import type { Token } from "../containerToken/containerToken.type.js";
8
11
  import type { ContainerRegistryOptions, RegistryListener } from "./containerRegistry.type.js";
9
12
  export declare class ContainerRegistry {
@@ -12,25 +15,36 @@ export declare class ContainerRegistry {
12
15
  private readonly allowDuplicates;
13
16
  constructor(options?: ContainerRegistryOptions);
14
17
  register<T>(token: RegistrationToken<T>, provider: ContainerProvider<T>, options?: CreateRegistrationOptions): ContainerRegistration<T>;
15
- registerRegistration<T>(registration: ContainerRegistration<T>): ContainerRegistration<T>;
16
18
  replace<T>(token: RegistrationToken<T>, provider: ContainerProvider<T>, options?: CreateRegistrationOptions): ContainerRegistration<T>;
17
19
  get<T>(token: RegistrationToken<T>): ContainerRegistration<T> | undefined;
18
- getOrThrow<T>(token: RegistrationToken<T>): ContainerRegistration<T>;
19
20
  has<T>(token: RegistrationToken<T>): boolean;
20
21
  remove<T>(token: RegistrationToken<T>): boolean;
21
- removeOrThrow<T>(token: RegistrationToken<T>): void;
22
22
  get size(): number;
23
23
  getAll(): readonly ContainerRegistration[];
24
24
  getTokens(): readonly Token<unknown>[];
25
- getByModule(module: string): readonly ContainerRegistration[];
26
- getByScope(scope: ContainerScope): readonly ContainerRegistration[];
27
- find(predicate: (r: ContainerRegistration) => boolean): readonly ContainerRegistration[];
28
- getMetadata<T>(token: RegistrationToken<T>): RegistrationMetadata | undefined;
29
25
  clear(): void;
30
26
  subscribe(listener: RegistryListener): () => void;
31
27
  clearListeners(): void;
28
+ /**
29
+ * Notifies all listeners. Listener errors are collected and rethrown as a
30
+ * single AggregateError after every listener has been notified — they are
31
+ * never silently swallowed.
32
+ */
32
33
  private emit;
34
+ /**
35
+ * Returns an immutable snapshot of the current registrations.
36
+ * Pass the result to {@link restore} to roll the registry back.
37
+ */
33
38
  snapshot(): readonly ContainerRegistration[];
39
+ /**
40
+ * Wholesale replacement of the registry's contents.
41
+ *
42
+ * Every existing registration is discarded and replaced by `regs` (entries
43
+ * are validated first; duplicate tokens in `regs` throw unless
44
+ * `allowDuplicates` is enabled, in which case the last entry wins).
45
+ * Emits a single RESTORE event so caches keyed on the old registrations
46
+ * can be evicted.
47
+ */
34
48
  restore(regs: readonly ContainerRegistration[]): void;
35
49
  }
36
50
  //# sourceMappingURL=containerRegistry.core.d.ts.map
@@ -1,11 +1,16 @@
1
1
  /**
2
2
  * Container registration registry.
3
+ *
4
+ * The registry stores normalized registrations and emits change events
5
+ * (REGISTER / REPLACE / REMOVE / CLEAR / RESTORE) so collaborators — notably
6
+ * the resolver's singleton cache — can react to mutations.
3
7
  */
4
- import { defineRegistration, getRegistrationToken, } from "../containerRegistration/containerRegistration.core.js";
5
- import { unwrapToken } from "../containerToken/containerToken.type.js";
8
+ import { assertValidProvider, assertValidRegistrationToken, defineRegistration, getRegistrationToken, } from "../containerRegistration/containerRegistration.core.js";
9
+ import { describeToken, unwrapToken, } from "../containerToken/containerToken.type.js";
6
10
  import { RegistryOperation } from "./containerRegistry.type.js";
7
11
  import { DuplicateRegistrationError, RegistrationNotFoundError, } from "@zudojs/errors";
8
- import { describeRegistryToken } from "./containerRegistry.error.js";
12
+ /** Token used for registry-wide events (CLEAR / RESTORE). */
13
+ const REGISTRY_EVENT_TOKEN = Symbol.for("zudojs:container:registry");
9
14
  export class ContainerRegistry {
10
15
  registrations = new Map();
11
16
  listeners = new Set();
@@ -16,7 +21,7 @@ export class ContainerRegistry {
16
21
  register(token, provider, options = {}) {
17
22
  const t = unwrapToken(token);
18
23
  if (this.registrations.has(t) && !this.allowDuplicates)
19
- throw new DuplicateRegistrationError(describeRegistryToken(t));
24
+ throw new DuplicateRegistrationError(describeToken(t));
20
25
  const prev = this.registrations.get(t);
21
26
  const reg = defineRegistration(t, provider, options);
22
27
  this.registrations.set(t, reg);
@@ -29,25 +34,10 @@ export class ContainerRegistry {
29
34
  });
30
35
  return reg;
31
36
  }
32
- registerRegistration(registration) {
33
- const t = getRegistrationToken(registration);
34
- if (this.registrations.has(t) && !this.allowDuplicates)
35
- throw new DuplicateRegistrationError(describeRegistryToken(t));
36
- const prev = this.registrations.get(t);
37
- this.registrations.set(t, registration);
38
- this.emit({
39
- operation: prev ? RegistryOperation.REPLACE : RegistryOperation.REGISTER,
40
- token: t,
41
- registration,
42
- previous: prev,
43
- timestamp: new Date(),
44
- });
45
- return registration;
46
- }
47
37
  replace(token, provider, options = {}) {
48
38
  const t = unwrapToken(token);
49
39
  if (!this.registrations.has(t))
50
- throw new RegistrationNotFoundError(describeRegistryToken(t));
40
+ throw new RegistrationNotFoundError(describeToken(t));
51
41
  const prev = this.registrations.get(t);
52
42
  const reg = defineRegistration(t, provider, options);
53
43
  this.registrations.set(t, reg);
@@ -63,12 +53,6 @@ export class ContainerRegistry {
63
53
  get(token) {
64
54
  return this.registrations.get(unwrapToken(token));
65
55
  }
66
- getOrThrow(token) {
67
- const r = this.get(token);
68
- if (!r)
69
- throw new RegistrationNotFoundError(describeRegistryToken(unwrapToken(token)));
70
- return r;
71
- }
72
56
  has(token) {
73
57
  return this.registrations.has(unwrapToken(token));
74
58
  }
@@ -87,10 +71,6 @@ export class ContainerRegistry {
87
71
  });
88
72
  return removed;
89
73
  }
90
- removeOrThrow(token) {
91
- if (!this.remove(unwrapToken(token)))
92
- throw new RegistrationNotFoundError(describeRegistryToken(unwrapToken(token)));
93
- }
94
74
  get size() {
95
75
  return this.registrations.size;
96
76
  }
@@ -100,25 +80,13 @@ export class ContainerRegistry {
100
80
  getTokens() {
101
81
  return [...this.registrations.keys()];
102
82
  }
103
- getByModule(module) {
104
- return [...this.registrations.values()].filter((r) => r.metadata.module === module);
105
- }
106
- getByScope(scope) {
107
- return [...this.registrations.values()].filter((r) => r.scope === scope);
108
- }
109
- find(predicate) {
110
- return [...this.registrations.values()].filter(predicate);
111
- }
112
- getMetadata(token) {
113
- return this.get(token)?.metadata;
114
- }
115
83
  clear() {
116
84
  if (this.registrations.size === 0)
117
85
  return;
118
86
  this.registrations.clear();
119
87
  this.emit({
120
88
  operation: RegistryOperation.CLEAR,
121
- token: Symbol.for("zudojs:container:registry"),
89
+ token: REGISTRY_EVENT_TOKEN,
122
90
  timestamp: new Date(),
123
91
  });
124
92
  }
@@ -131,23 +99,58 @@ export class ContainerRegistry {
131
99
  clearListeners() {
132
100
  this.listeners.clear();
133
101
  }
102
+ /**
103
+ * Notifies all listeners. Listener errors are collected and rethrown as a
104
+ * single AggregateError after every listener has been notified — they are
105
+ * never silently swallowed.
106
+ */
134
107
  emit(event) {
108
+ const errors = [];
135
109
  for (const l of this.listeners) {
136
110
  try {
137
111
  l(event);
138
112
  }
139
- catch {
140
- /* noop */
113
+ catch (error) {
114
+ errors.push(error);
141
115
  }
142
116
  }
117
+ if (errors.length > 0)
118
+ throw new AggregateError(errors, `${errors.length} container registry listener(s) failed while handling "${event.operation}".`);
143
119
  }
120
+ /**
121
+ * Returns an immutable snapshot of the current registrations.
122
+ * Pass the result to {@link restore} to roll the registry back.
123
+ */
144
124
  snapshot() {
145
125
  return this.getAll();
146
126
  }
127
+ /**
128
+ * Wholesale replacement of the registry's contents.
129
+ *
130
+ * Every existing registration is discarded and replaced by `regs` (entries
131
+ * are validated first; duplicate tokens in `regs` throw unless
132
+ * `allowDuplicates` is enabled, in which case the last entry wins).
133
+ * Emits a single RESTORE event so caches keyed on the old registrations
134
+ * can be evicted.
135
+ */
147
136
  restore(regs) {
137
+ const next = new Map();
138
+ for (const r of regs) {
139
+ assertValidRegistrationToken(r.token);
140
+ assertValidProvider(r.provider);
141
+ const t = getRegistrationToken(r);
142
+ if (next.has(t) && !this.allowDuplicates)
143
+ throw new DuplicateRegistrationError(describeToken(t));
144
+ next.set(t, r);
145
+ }
148
146
  this.registrations.clear();
149
- for (const r of regs)
150
- this.registrations.set(getRegistrationToken(r), r);
147
+ for (const [t, r] of next)
148
+ this.registrations.set(t, r);
149
+ this.emit({
150
+ operation: RegistryOperation.RESTORE,
151
+ token: REGISTRY_EVENT_TOKEN,
152
+ timestamp: new Date(),
153
+ });
151
154
  }
152
155
  }
153
156
  //# sourceMappingURL=containerRegistry.core.js.map
@@ -14,7 +14,9 @@ export declare enum RegistryOperation {
14
14
  REGISTER = "register",
15
15
  REPLACE = "replace",
16
16
  REMOVE = "remove",
17
- CLEAR = "clear"
17
+ CLEAR = "clear",
18
+ /** Wholesale replacement of all registrations via `restore()`. */
19
+ RESTORE = "restore"
18
20
  }
19
21
  /**
20
22
  * Event emitted when the registry changes.
@@ -10,5 +10,7 @@ export var RegistryOperation;
10
10
  RegistryOperation["REPLACE"] = "replace";
11
11
  RegistryOperation["REMOVE"] = "remove";
12
12
  RegistryOperation["CLEAR"] = "clear";
13
+ /** Wholesale replacement of all registrations via `restore()`. */
14
+ RegistryOperation["RESTORE"] = "restore";
13
15
  })(RegistryOperation || (RegistryOperation = {}));
14
16
  //# sourceMappingURL=containerRegistry.type.js.map
@@ -4,6 +4,5 @@
4
4
  * Service registry storage and lookup.
5
5
  */
6
6
  export * from "./containerRegistry.type.js";
7
- export { describeRegistryToken } from "./containerRegistry.error.js";
8
7
  export * from "./containerRegistry.core.js";
9
8
  //# sourceMappingURL=index.d.ts.map
@@ -4,6 +4,5 @@
4
4
  * Service registry storage and lookup.
5
5
  */
6
6
  export * from "./containerRegistry.type.js";
7
- export { describeRegistryToken } from "./containerRegistry.error.js";
8
7
  export * from "./containerRegistry.core.js";
9
8
  //# sourceMappingURL=index.js.map
@@ -1,26 +1,67 @@
1
1
  /**
2
2
  * Dependency resolver for Zudojs.
3
+ *
4
+ * Lifetime semantics:
5
+ * - SINGLETON instances are always looked up in and stored to the resolver's
6
+ * root singleton cache, no matter where the resolution happens (root or
7
+ * scope). A scope can therefore never re-create or shadow a singleton.
8
+ * - SCOPED instances live in the scope cache supplied via
9
+ * `ResolutionOptions.cache`. Resolving a SCOPED registration without a
10
+ * scope cache throws a ScopedResolutionError; a SCOPED dependency of a
11
+ * SINGLETON throws a CaptiveDependencyError.
12
+ * - TRANSIENT instances are never cached.
13
+ *
14
+ * Every freshly created instance (any lifetime, never a cache hit) is
15
+ * reported through `ResolutionOptions.onInstanceCreated` in creation order,
16
+ * so owners can track transitively created dependencies for disposal — not
17
+ * just the top-level result of a `resolve()` call.
18
+ *
19
+ * Factories registered as SINGLETON or SCOPED must be synchronous: a Promise
20
+ * result throws an AsyncProviderError instead of being cached as the instance.
21
+ *
22
+ * The resolver subscribes to registry change events: REPLACE/REMOVE evict the
23
+ * affected token's cached singleton, CLEAR/RESTORE evict all cached
24
+ * singletons. Each eviction is reported through the `onSingletonEvicted`
25
+ * callback so the owning container can dispose the instance.
3
26
  */
4
27
  import type { RegistrationToken } from "../containerRegistration/containerRegistration.core.js";
5
28
  import type { ContainerRegistry } from "../containerRegistry/containerRegistry.core.js";
29
+ import type { Token } from "../containerToken/containerToken.type.js";
6
30
  import type { ResolutionCache, ResolutionOptions, ResolutionResult } from "./containerResolution.type.js";
7
31
  export declare class ContainerResolver {
8
32
  private readonly registry;
9
33
  private readonly singletonCache;
10
- constructor(registry: ContainerRegistry);
34
+ private readonly onSingletonEvicted;
35
+ constructor(registry: ContainerRegistry, onSingletonEvicted?: (token: Token<unknown>) => void);
11
36
  resolve<T>(token: RegistrationToken<T>, options?: ResolutionOptions): T;
12
37
  resolveDetailed<T>(token: RegistrationToken<T>, options?: ResolutionOptions): ResolutionResult<T>;
13
38
  private resolveInternal;
14
39
  private createInstance;
15
- private createFromFactory;
16
- private createFromClass;
17
- createScope(): ResolutionCache;
18
- clearSingletons(): void;
19
- hasSingleton<T>(token: RegistrationToken<T>): boolean;
20
- getSingleton<T>(token: RegistrationToken<T>): T | undefined;
21
- removeSingleton<T>(token: RegistrationToken<T>): boolean;
22
- clearScope(cache: ResolutionCache): void;
40
+ /**
41
+ * Creates an empty scope cache for SCOPED instances. When `parent` is
42
+ * given, lookups fall back to it (nested scope semantics) while writes stay
43
+ * local to the new cache.
44
+ */
45
+ createScope(parent?: ResolutionCache): ResolutionCache;
46
+ /** Tokens currently held in the singleton cache. */
47
+ getCachedSingletonTokens(): readonly Token<unknown>[];
48
+ /**
49
+ * Clears the singleton cache WITHOUT invoking eviction callbacks.
50
+ * Callers are responsible for disposing the previously cached instances.
51
+ */
52
+ clearSingletonCache(): void;
23
53
  resolveMany<T>(tokens: readonly RegistrationToken<T>[], options?: ResolutionOptions): T[];
24
- canResolve<T>(token: RegistrationToken<T>): boolean;
54
+ canResolve<T>(token: RegistrationToken<T>, autoRegisterClasses?: boolean): boolean;
55
+ private handleRegistryChange;
56
+ private evictSingleton;
57
+ /**
58
+ * Evicts every cached singleton whose `useExisting` chain ends at `target`.
59
+ *
60
+ * A cached alias holds the target's instance under its own token, so
61
+ * evicting the target alone left the alias serving the old — by now
62
+ * disposed — instance after `replace()`/`remove()`.
63
+ */
64
+ private evictAliasesOf;
65
+ private aliasChainReaches;
25
66
  }
26
67
  //# sourceMappingURL=containerResolution.core.d.ts.map