katagami 2.0.0 → 2.2.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.
package/dist/index.js CHANGED
@@ -14,22 +14,22 @@ function createContainer() {
14
14
 
15
15
  class Container {
16
16
  registrations;
17
- instances;
17
+ singletonCache;
18
18
  resolvingTokens;
19
19
  disposed = false;
20
20
  [INTERNALS];
21
21
  constructor() {
22
22
  this.registrations = new Map;
23
- this.instances = new Map;
23
+ this.singletonCache = new Map;
24
24
  this.resolvingTokens = new Set;
25
25
  this[INTERNALS] = {
26
- instances: this.instances,
27
26
  isDisposed: () => this.disposed,
28
27
  markDisposed: () => {
29
28
  this.disposed = true;
30
29
  },
31
- ownInstances: this.instances,
32
- registrations: this.registrations
30
+ ownCache: this.singletonCache,
31
+ registrations: this.registrations,
32
+ singletonCache: this.singletonCache
33
33
  };
34
34
  }
35
35
  registerSingleton(token, factory) {
@@ -41,27 +41,40 @@ class Container {
41
41
  registerScoped(token, factory) {
42
42
  return this.addRegistration(token, factory, "scoped");
43
43
  }
44
+ use(source) {
45
+ for (const [token, registrations] of source[INTERNALS].registrations) {
46
+ this.registrations.set(token, [...registrations]);
47
+ }
48
+ return this;
49
+ }
44
50
  resolve(token) {
45
51
  return this.resolveToken(token, true);
46
52
  }
47
53
  tryResolve(token) {
48
54
  return this.resolveToken(token, false);
49
55
  }
56
+ resolveAll(token) {
57
+ return this.resolveAllTokens(token, true);
58
+ }
59
+ tryResolveAll(token) {
60
+ return this.resolveAllTokens(token, false);
61
+ }
50
62
  resolveToken(token, required) {
51
63
  if (this.disposed) {
52
64
  throw new ContainerError("Cannot resolve from a disposed container.");
53
65
  }
54
- const cached = this.instances.get(token);
55
- if (cached !== undefined) {
56
- return cached;
57
- }
58
- const registration = this.registrations.get(token);
59
- if (registration === undefined) {
66
+ const registrations = this.registrations.get(token);
67
+ if (registrations === undefined || registrations.length === 0) {
60
68
  if (required) {
61
69
  throw new ContainerError(`Token "${tokenToString(token)}" is not registered.`);
62
70
  }
63
71
  return;
64
72
  }
73
+ const registration = registrations[registrations.length - 1];
74
+ const cached = this.singletonCache.get(registration);
75
+ if (cached !== undefined) {
76
+ return cached;
77
+ }
65
78
  if (registration.lifetime === "scoped") {
66
79
  throw new ContainerError(`Cannot resolve scoped token "${tokenToString(token)}" from the root container. Use createScope() to create a scope first.`);
67
80
  }
@@ -72,15 +85,55 @@ class Container {
72
85
  try {
73
86
  const instance = registration.factory(this);
74
87
  if (registration.lifetime === "singleton") {
75
- this.instances.set(token, instance);
88
+ this.singletonCache.set(registration, instance);
76
89
  }
77
90
  return instance;
78
91
  } finally {
79
92
  this.resolvingTokens.delete(token);
80
93
  }
81
94
  }
95
+ resolveAllTokens(token, required) {
96
+ if (this.disposed) {
97
+ throw new ContainerError("Cannot resolve from a disposed container.");
98
+ }
99
+ const registrations = this.registrations.get(token);
100
+ if (registrations === undefined || registrations.length === 0) {
101
+ if (required) {
102
+ throw new ContainerError(`Token "${tokenToString(token)}" is not registered.`);
103
+ }
104
+ return;
105
+ }
106
+ if (this.resolvingTokens.has(token)) {
107
+ throw new ContainerError(`Circular dependency detected: ${buildCircularPath(this.resolvingTokens, token)}`);
108
+ }
109
+ this.resolvingTokens.add(token);
110
+ try {
111
+ return registrations.map((registration) => {
112
+ const reg = registration;
113
+ const cached = this.singletonCache.get(registration);
114
+ if (cached !== undefined) {
115
+ return cached;
116
+ }
117
+ if (reg.lifetime === "scoped") {
118
+ throw new ContainerError(`Cannot resolve scoped token "${tokenToString(token)}" from the root container. Use createScope() to create a scope first.`);
119
+ }
120
+ const instance = reg.factory(this);
121
+ if (reg.lifetime === "singleton") {
122
+ this.singletonCache.set(registration, instance);
123
+ }
124
+ return instance;
125
+ });
126
+ } finally {
127
+ this.resolvingTokens.delete(token);
128
+ }
129
+ }
82
130
  addRegistration(token, factory, lifetime) {
83
- this.registrations.set(token, { factory, lifetime });
131
+ const existing = this.registrations.get(token);
132
+ if (existing !== undefined) {
133
+ existing.push({ factory, lifetime });
134
+ } else {
135
+ this.registrations.set(token, [{ factory, lifetime }]);
136
+ }
84
137
  return this;
85
138
  }
86
139
  }
@@ -14,12 +14,12 @@ export declare const INTERNALS: unique symbol;
14
14
  * @internal
15
15
  */
16
16
  export interface ContainerInternals {
17
- /** All registrations (singleton / transient / scoped). */
18
- readonly registrations: Map<unknown, Registration>;
19
- /** Instance cache used during resolution (Container: singletons, Scope: singletonInstances). */
20
- readonly instances: Map<unknown, unknown>;
21
- /** Instances owned by this container / scope (disposal target). */
22
- readonly ownInstances: Map<unknown, unknown>;
17
+ /** All registrations (singleton / transient / scoped). Each token maps to an array of registrations. */
18
+ readonly registrations: Map<unknown, Registration[]>;
19
+ /** Singleton cache keyed by Registration object (Container: singletons, Scope: shared with parent). */
20
+ readonly singletonCache: Map<Registration, unknown>;
21
+ /** Instances owned by this container / scope (disposal target), keyed by Registration object. */
22
+ readonly ownCache: Map<Registration, unknown>;
23
23
  /** Whether this container / scope has been disposed. */
24
24
  isDisposed(): boolean;
25
25
  /** Mark this container / scope as disposed. */
@@ -0,0 +1,88 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
6
+ var __toCommonJS = (from) => {
7
+ var entry = __moduleCache.get(from), desc;
8
+ if (entry)
9
+ return entry;
10
+ entry = __defProp({}, "__esModule", { value: true });
11
+ if (from && typeof from === "object" || typeof from === "function")
12
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
13
+ get: () => from[key],
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ }));
16
+ __moduleCache.set(from, entry);
17
+ return entry;
18
+ };
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, {
22
+ get: all[name],
23
+ enumerable: true,
24
+ configurable: true,
25
+ set: (newValue) => all[name] = () => newValue
26
+ });
27
+ };
28
+
29
+ // src/lazy/index.ts
30
+ var exports_lazy = {};
31
+ __export(exports_lazy, {
32
+ lazy: () => lazy
33
+ });
34
+ module.exports = __toCommonJS(exports_lazy);
35
+ function lazy(source, token) {
36
+ let instance;
37
+ let resolved = false;
38
+ const ensureResolved = () => {
39
+ if (!resolved) {
40
+ instance = source.resolve(token);
41
+ resolved = true;
42
+ }
43
+ return instance;
44
+ };
45
+ const proxyTarget = Object.create(null);
46
+ return new Proxy(proxyTarget, {
47
+ defineProperty(_, prop, desc) {
48
+ return Reflect.defineProperty(ensureResolved(), prop, desc);
49
+ },
50
+ deleteProperty(_, prop) {
51
+ return Reflect.deleteProperty(ensureResolved(), prop);
52
+ },
53
+ get(_, prop) {
54
+ const target = ensureResolved();
55
+ const value = Reflect.get(target, prop, target);
56
+ if (typeof value === "function") {
57
+ return value.bind(target);
58
+ }
59
+ return value;
60
+ },
61
+ getOwnPropertyDescriptor(_, prop) {
62
+ return Reflect.getOwnPropertyDescriptor(ensureResolved(), prop);
63
+ },
64
+ getPrototypeOf() {
65
+ return Reflect.getPrototypeOf(ensureResolved());
66
+ },
67
+ has(_, prop) {
68
+ return Reflect.has(ensureResolved(), prop);
69
+ },
70
+ isExtensible() {
71
+ return Reflect.isExtensible(ensureResolved());
72
+ },
73
+ ownKeys() {
74
+ return Reflect.ownKeys(ensureResolved());
75
+ },
76
+ preventExtensions() {
77
+ Reflect.preventExtensions(ensureResolved());
78
+ Reflect.preventExtensions(proxyTarget);
79
+ return true;
80
+ },
81
+ set(_, prop, value) {
82
+ return Reflect.set(ensureResolved(), prop, value, ensureResolved());
83
+ },
84
+ setPrototypeOf(_, proto) {
85
+ return Reflect.setPrototypeOf(ensureResolved(), proto);
86
+ }
87
+ });
88
+ }
@@ -0,0 +1,35 @@
1
+ import type { Container } from '../container';
2
+ import type { DisposableContainer, DisposableScope } from '../disposable';
3
+ import type { AbstractConstructor } from '../resolver';
4
+ import type { Scope } from '../scope';
5
+ /**
6
+ * Create a lazy proxy that defers resolution until the first property access.
7
+ *
8
+ * The returned object looks and behaves like `V`, but the underlying instance
9
+ * is not created until a property is read, written, or otherwise accessed.
10
+ * Once resolved the instance is cached — subsequent accesses hit the cache.
11
+ *
12
+ * Only **sync class tokens** are supported. Async tokens and PropertyKey tokens
13
+ * are rejected at the type level.
14
+ *
15
+ * @param source A Container, Scope, DisposableContainer, or DisposableScope
16
+ * @param token A sync class constructor token
17
+ * @returns A proxy that transparently forwards to the lazily-resolved instance
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { createContainer } from 'katagami';
22
+ * import { lazy } from 'katagami/lazy';
23
+ *
24
+ * const container = createContainer()
25
+ * .registerSingleton(HeavyService, () => new HeavyService());
26
+ *
27
+ * const service = lazy(container, HeavyService);
28
+ * // Instance is NOT created yet
29
+ * service.doSomething(); // resolved here, then cached
30
+ * ```
31
+ */
32
+ export declare function lazy<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, V>(source: Container<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>, token: AbstractConstructor<V> & Sync): V;
33
+ export declare function lazy<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, V>(source: Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>, token: AbstractConstructor<V> & (Sync | ScopedSync)): V;
34
+ export declare function lazy<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, V>(source: DisposableContainer<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>, token: AbstractConstructor<V> & Sync): V;
35
+ export declare function lazy<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor, V>(source: DisposableScope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>, token: AbstractConstructor<V> & (Sync | ScopedSync)): V;
@@ -0,0 +1,58 @@
1
+ // src/lazy/index.ts
2
+ function lazy(source, token) {
3
+ let instance;
4
+ let resolved = false;
5
+ const ensureResolved = () => {
6
+ if (!resolved) {
7
+ instance = source.resolve(token);
8
+ resolved = true;
9
+ }
10
+ return instance;
11
+ };
12
+ const proxyTarget = Object.create(null);
13
+ return new Proxy(proxyTarget, {
14
+ defineProperty(_, prop, desc) {
15
+ return Reflect.defineProperty(ensureResolved(), prop, desc);
16
+ },
17
+ deleteProperty(_, prop) {
18
+ return Reflect.deleteProperty(ensureResolved(), prop);
19
+ },
20
+ get(_, prop) {
21
+ const target = ensureResolved();
22
+ const value = Reflect.get(target, prop, target);
23
+ if (typeof value === "function") {
24
+ return value.bind(target);
25
+ }
26
+ return value;
27
+ },
28
+ getOwnPropertyDescriptor(_, prop) {
29
+ return Reflect.getOwnPropertyDescriptor(ensureResolved(), prop);
30
+ },
31
+ getPrototypeOf() {
32
+ return Reflect.getPrototypeOf(ensureResolved());
33
+ },
34
+ has(_, prop) {
35
+ return Reflect.has(ensureResolved(), prop);
36
+ },
37
+ isExtensible() {
38
+ return Reflect.isExtensible(ensureResolved());
39
+ },
40
+ ownKeys() {
41
+ return Reflect.ownKeys(ensureResolved());
42
+ },
43
+ preventExtensions() {
44
+ Reflect.preventExtensions(ensureResolved());
45
+ Reflect.preventExtensions(proxyTarget);
46
+ return true;
47
+ },
48
+ set(_, prop, value) {
49
+ return Reflect.set(ensureResolved(), prop, value, ensureResolved());
50
+ },
51
+ setPrototypeOf(_, proto) {
52
+ return Reflect.setPrototypeOf(ensureResolved(), proto);
53
+ }
54
+ });
55
+ }
56
+ export {
57
+ lazy
58
+ };
@@ -30,6 +30,31 @@ export interface Resolver<T, Sync extends AbstractConstructor = AbstractConstruc
30
30
  tryResolve<K extends keyof T>(token: K): T[K] | undefined;
31
31
  tryResolve<V>(token: AbstractConstructor<V>): V | Promise<V> | undefined;
32
32
  tryResolve(token: PropertyKey): unknown;
33
+ /**
34
+ * Resolve all instances for the given token.
35
+ *
36
+ * Returns an array of instances from all registrations for the token.
37
+ *
38
+ * @param token A registered token
39
+ * @returns An array of instances associated with the token
40
+ */
41
+ resolveAll<V>(token: AbstractConstructor<V> & Async): Promise<V>[];
42
+ resolveAll<V>(token: AbstractConstructor<V> & Sync): V[];
43
+ resolveAll<K extends keyof T>(token: K): T[K][];
44
+ /**
45
+ * Try to resolve all instances for the given token.
46
+ *
47
+ * Returns `undefined` instead of throwing when the token is not registered.
48
+ * Other errors (circular dependency, disposed container) are still thrown.
49
+ *
50
+ * @param token A token to resolve
51
+ * @returns An array of instances associated with the token, or `undefined` if not registered
52
+ */
53
+ tryResolveAll<V>(token: AbstractConstructor<V> & Async): Promise<V>[] | undefined;
54
+ tryResolveAll<V>(token: AbstractConstructor<V> & Sync): V[] | undefined;
55
+ tryResolveAll<K extends keyof T>(token: K): T[K][] | undefined;
56
+ tryResolveAll<V>(token: AbstractConstructor<V>): (V | Promise<V>)[] | undefined;
57
+ tryResolveAll(token: PropertyKey): unknown;
33
58
  }
34
59
  /**
35
60
  * Lifetime of a registration.
@@ -76,29 +76,29 @@ function createScope(source) {
76
76
  if (internals.isDisposed()) {
77
77
  throw new ContainerError("Cannot create a scope from a disposed container.");
78
78
  }
79
- return new Scope(internals.registrations, internals.instances);
79
+ return new Scope(internals.registrations, internals.singletonCache);
80
80
  }
81
81
 
82
82
  class Scope {
83
83
  registrations;
84
- singletonInstances;
85
- scopedInstances;
84
+ singletonCache;
85
+ scopedCache;
86
86
  resolvingTokens;
87
87
  disposed = false;
88
88
  [INTERNALS];
89
- constructor(registrations, singletonInstances) {
89
+ constructor(registrations, singletonCache) {
90
90
  this.registrations = registrations;
91
- this.singletonInstances = singletonInstances;
92
- this.scopedInstances = new Map;
91
+ this.singletonCache = singletonCache;
92
+ this.scopedCache = new Map;
93
93
  this.resolvingTokens = new Set;
94
94
  this[INTERNALS] = {
95
- instances: this.singletonInstances,
96
95
  isDisposed: () => this.disposed,
97
96
  markDisposed: () => {
98
97
  this.disposed = true;
99
98
  },
100
- ownInstances: this.scopedInstances,
101
- registrations: this.registrations
99
+ ownCache: this.scopedCache,
100
+ registrations: this.registrations,
101
+ singletonCache: this.singletonCache
102
102
  };
103
103
  }
104
104
  resolve(token) {
@@ -107,25 +107,32 @@ class Scope {
107
107
  tryResolve(token) {
108
108
  return this.resolveToken(token, false);
109
109
  }
110
+ resolveAll(token) {
111
+ return this.resolveAllTokens(token, true);
112
+ }
113
+ tryResolveAll(token) {
114
+ return this.resolveAllTokens(token, false);
115
+ }
110
116
  resolveToken(token, required) {
111
117
  if (this.disposed) {
112
118
  throw new ContainerError("Cannot resolve from a disposed scope.");
113
119
  }
114
- const singletonCached = this.singletonInstances.get(token);
120
+ const registrations = this.registrations.get(token);
121
+ if (registrations === undefined || registrations.length === 0) {
122
+ if (required) {
123
+ throw new ContainerError(`Token "${tokenToString(token)}" is not registered.`);
124
+ }
125
+ return;
126
+ }
127
+ const registration = registrations[registrations.length - 1];
128
+ const singletonCached = this.singletonCache.get(registration);
115
129
  if (singletonCached !== undefined) {
116
130
  return singletonCached;
117
131
  }
118
- const scopedCached = this.scopedInstances.get(token);
132
+ const scopedCached = this.scopedCache.get(registration);
119
133
  if (scopedCached !== undefined) {
120
134
  return scopedCached;
121
135
  }
122
- const registration = this.registrations.get(token);
123
- if (registration === undefined) {
124
- if (required) {
125
- throw new ContainerError(`Token "${tokenToString(token)}" is not registered.`);
126
- }
127
- return;
128
- }
129
136
  if (this.resolvingTokens.has(token)) {
130
137
  throw new ContainerError(`Circular dependency detected: ${buildCircularPath(this.resolvingTokens, token)}`);
131
138
  }
@@ -133,13 +140,51 @@ class Scope {
133
140
  try {
134
141
  const instance = registration.factory(this);
135
142
  if (registration.lifetime === "singleton") {
136
- this.singletonInstances.set(token, instance);
143
+ this.singletonCache.set(registration, instance);
137
144
  } else if (registration.lifetime === "scoped") {
138
- this.scopedInstances.set(token, instance);
145
+ this.scopedCache.set(registration, instance);
139
146
  }
140
147
  return instance;
141
148
  } finally {
142
149
  this.resolvingTokens.delete(token);
143
150
  }
144
151
  }
152
+ resolveAllTokens(token, required) {
153
+ if (this.disposed) {
154
+ throw new ContainerError("Cannot resolve from a disposed scope.");
155
+ }
156
+ const registrations = this.registrations.get(token);
157
+ if (registrations === undefined || registrations.length === 0) {
158
+ if (required) {
159
+ throw new ContainerError(`Token "${tokenToString(token)}" is not registered.`);
160
+ }
161
+ return;
162
+ }
163
+ if (this.resolvingTokens.has(token)) {
164
+ throw new ContainerError(`Circular dependency detected: ${buildCircularPath(this.resolvingTokens, token)}`);
165
+ }
166
+ this.resolvingTokens.add(token);
167
+ try {
168
+ return registrations.map((registration) => {
169
+ const reg = registration;
170
+ const singletonCached = this.singletonCache.get(registration);
171
+ if (singletonCached !== undefined) {
172
+ return singletonCached;
173
+ }
174
+ const scopedCached = this.scopedCache.get(registration);
175
+ if (scopedCached !== undefined) {
176
+ return scopedCached;
177
+ }
178
+ const instance = reg.factory(this);
179
+ if (reg.lifetime === "singleton") {
180
+ this.singletonCache.set(registration, instance);
181
+ } else if (reg.lifetime === "scoped") {
182
+ this.scopedCache.set(registration, instance);
183
+ }
184
+ return instance;
185
+ });
186
+ } finally {
187
+ this.resolvingTokens.delete(token);
188
+ }
189
+ }
145
190
  }
@@ -1,18 +1,21 @@
1
1
  import type { Container } from '../container';
2
+ import type { DisposableContainer, DisposableScope } from '../disposable';
2
3
  import { type ContainerInternals, INTERNALS } from '../internal';
3
4
  import type { AbstractConstructor, Registration } from '../resolver';
4
5
  /**
5
- * Create a new scope (child container) from a Container or an existing Scope.
6
+ * Create a new scope (child container) from a Container, Scope, or their disposable variants.
6
7
  *
7
8
  * The scope inherits all registrations from the source.
8
9
  * Singleton instances are shared with the parent, while scoped instances are local to the scope.
9
10
  *
10
- * @param source A Container or Scope to create a child scope from
11
+ * @param source A Container, Scope, DisposableContainer, or DisposableScope to create a child scope from
11
12
  * @returns A new Scope instance
12
13
  * @throws ContainerError if the source has been disposed
13
14
  */
14
15
  export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor>(source: Container<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
15
16
  export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor>(source: Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
17
+ export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor>(source: DisposableContainer<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
18
+ export declare function createScope<T, Sync extends AbstractConstructor, Async extends AbstractConstructor, ScopedT, ScopedSync extends AbstractConstructor, ScopedAsync extends AbstractConstructor>(source: DisposableScope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>): Scope<T, Sync, Async, ScopedT, ScopedSync, ScopedAsync>;
16
19
  /**
17
20
  * Scoped child container.
18
21
  *
@@ -29,8 +32,8 @@ export declare function createScope<T, Sync extends AbstractConstructor, Async e
29
32
  */
30
33
  export declare class Scope<T = Record<never, never>, Sync extends AbstractConstructor = never, Async extends AbstractConstructor = never, ScopedT = Record<never, never>, ScopedSync extends AbstractConstructor = never, ScopedAsync extends AbstractConstructor = never> {
31
34
  private readonly registrations;
32
- private readonly singletonInstances;
33
- private readonly scopedInstances;
35
+ private readonly singletonCache;
36
+ private readonly scopedCache;
34
37
  private readonly resolvingTokens;
35
38
  private disposed;
36
39
  /**
@@ -39,7 +42,7 @@ export declare class Scope<T = Record<never, never>, Sync extends AbstractConstr
39
42
  * @internal
40
43
  */
41
44
  readonly [INTERNALS]: ContainerInternals;
42
- constructor(registrations: Map<unknown, Registration>, singletonInstances: Map<unknown, unknown>);
45
+ constructor(registrations: Map<unknown, Registration[]>, singletonCache: Map<Registration, unknown>);
43
46
  /**
44
47
  * Resolve an instance for the given token.
45
48
  *
@@ -68,12 +71,49 @@ export declare class Scope<T = Record<never, never>, Sync extends AbstractConstr
68
71
  tryResolve<K extends keyof (T & ScopedT)>(token: K): (T & ScopedT)[K] | undefined;
69
72
  tryResolve<V>(token: AbstractConstructor<V>): V | Promise<V> | undefined;
70
73
  tryResolve(token: PropertyKey): unknown;
74
+ /**
75
+ * Resolve all instances for the given token.
76
+ *
77
+ * Returns an array of instances from all registered factories for the token,
78
+ * in registration order.
79
+ *
80
+ * @param token A registered token
81
+ * @returns An array of instances associated with the token
82
+ * @throws ContainerError if the token is not registered
83
+ */
84
+ resolveAll<V>(token: AbstractConstructor<V> & (Async | ScopedAsync)): Promise<V>[];
85
+ resolveAll<V>(token: AbstractConstructor<V> & (Sync | ScopedSync)): V[];
86
+ resolveAll<K extends keyof (T & ScopedT)>(token: K): (T & ScopedT)[K][];
87
+ /**
88
+ * Try to resolve all instances for the given token.
89
+ *
90
+ * Returns `undefined` instead of throwing when the token is not registered.
91
+ * Other errors (circular dependency, disposed scope) are still thrown.
92
+ *
93
+ * @param token A token to resolve
94
+ * @returns An array of instances associated with the token, or `undefined` if not registered
95
+ */
96
+ tryResolveAll<V>(token: AbstractConstructor<V> & (Async | ScopedAsync)): Promise<V>[] | undefined;
97
+ tryResolveAll<V>(token: AbstractConstructor<V> & (Sync | ScopedSync)): V[] | undefined;
98
+ tryResolveAll<K extends keyof (T & ScopedT)>(token: K): (T & ScopedT)[K][] | undefined;
99
+ tryResolveAll<V>(token: AbstractConstructor<V>): (V | Promise<V>)[] | undefined;
100
+ tryResolveAll(token: PropertyKey): unknown;
71
101
  /**
72
102
  * Internal resolution logic shared by resolve and tryResolve.
103
+ * Resolves the last registered factory for the token.
73
104
  *
74
105
  * @param token Token to resolve
75
106
  * @param required If true, throws when the token is not registered. If false, returns undefined.
76
107
  * @returns The resolved instance, or undefined if not registered and required is false
77
108
  */
78
109
  private resolveToken;
110
+ /**
111
+ * Internal resolution logic shared by resolveAll and tryResolveAll.
112
+ * Resolves all registered factories for the token.
113
+ *
114
+ * @param token Token to resolve
115
+ * @param required If true, throws when the token is not registered. If false, returns undefined.
116
+ * @returns An array of resolved instances, or undefined if not registered and required is false
117
+ */
118
+ private resolveAllTokens;
79
119
  }