@fluojs/di 1.0.2 → 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.
package/README.ko.md CHANGED
@@ -163,6 +163,7 @@ const service = await container.resolve(DataService);
163
163
  | `register(...providers)` | 하나 이상의 프로바이더를 등록합니다. |
164
164
  | `override(...providers)` | 기존 provider를 교체하고 cached instance를 무효화하며 오래된 instance를 dispose합니다. |
165
165
  | `resolve<T>(token)` | 토큰을 인스턴스로 비동기 해석합니다. |
166
+ | `inspectResolutionState()` | cache ownership을 보존해야 하는 testing/tooling helper를 위한 지원 대상 framework-owned container introspection seam을 노출합니다. 애플리케이션 코드는 `has(...)`와 `resolve(...)`를 우선 사용하세요. |
166
167
  | `createRequestScope()` | 요청 스코프 의존성을 위한 자식 컨테이너를 생성합니다. |
167
168
  | `has(token)` | 컨테이너나 부모에 토큰이 등록되어 있는지 확인합니다. |
168
169
  | `hasRequestScopedDependency(token)` | 토큰 해석 시 provider 그래프에 request-scoped 의존성이나 순환이 있어 request-scope 컨테이너가 필요할 수 있는지 확인합니다. |
@@ -175,6 +176,7 @@ const service = await container.resolve(DataService);
175
176
  | Provider types | `Provider`, `ClassProvider`, `FactoryProvider`, `ValueProvider`, `ExistingProvider`는 `register(...)`와 `override(...)`가 받는 공개 registration shape를 설명합니다. |
176
177
  | Token wrapper types | `ForwardRefFn`과 `OptionalToken`은 `forwardRef(...)`와 `optional(...)`이 반환하는 wrapper 값을 설명합니다. |
177
178
  | Container helper types | `ClassType`, `Disposable`, `RequestScopeContainer`는 typed provider 선언, teardown hook, request-scope helper 경계를 지원합니다. |
179
+ | `ContainerResolutionState` | framework testing/tooling integration을 위해 `inspectResolutionState()`가 반환하는 공개 introspection record입니다. |
178
180
  | `NormalizedProvider` | 컨테이너가 검증한 provider record shape를 위한 compatibility-only 공개 타입입니다. provider를 작성할 때는 `Provider`나 구체 provider interface를 우선 사용하세요. normalized record 생성은 컨테이너가 소유합니다. |
179
181
  | `DiErrorContext` | DI error에 붙는 구조화된 context입니다. 로그와 테스트가 token, scope, module, dependency chain, hint를 검사할 수 있게 합니다. |
180
182
  | 에러 클래스 | `InvalidProviderError`, `ContainerResolutionError`, `RequestScopeResolutionError`, `ScopeMismatchError`, `CircularDependencyError`, `DuplicateProviderError`. |
package/README.md CHANGED
@@ -163,6 +163,7 @@ Ensure all required providers are registered in the container. If you use `creat
163
163
  | `register(...providers)` | Registers one or more providers. |
164
164
  | `override(...providers)` | Replaces existing providers, invalidates cached instances, and disposes stale instances. |
165
165
  | `resolve<T>(token)` | Asynchronously resolves a token to an instance. |
166
+ | `inspectResolutionState()` | Exposes the supported framework-owned container introspection seam for testing/tooling helpers that must preserve cache ownership. Prefer `has(...)` and `resolve(...)` for application code. |
166
167
  | `createRequestScope()` | Creates a child container for request-scoped dependencies. |
167
168
  | `has(token)` | Checks if a token is registered in the container or its parents. |
168
169
  | `hasRequestScopedDependency(token)` | Checks whether resolving a token may require a request-scope container because its provider graph contains request-scoped dependencies or is cyclic. |
@@ -175,6 +176,7 @@ Ensure all required providers are registered in the container. If you use `creat
175
176
  | Provider types | `Provider`, `ClassProvider`, `FactoryProvider`, `ValueProvider`, and `ExistingProvider` describe the public registration shapes accepted by `register(...)` and `override(...)`. |
176
177
  | Token wrapper types | `ForwardRefFn` and `OptionalToken` describe the wrapper values returned by `forwardRef(...)` and `optional(...)`. |
177
178
  | Container helper types | `ClassType`, `Disposable`, and `RequestScopeContainer` support typed provider declarations, teardown hooks, and request-scope helper boundaries. |
179
+ | `ContainerResolutionState` | Public introspection record returned by `inspectResolutionState()` for framework testing/tooling integrations. |
178
180
  | `NormalizedProvider` | Compatibility-only public type for the container's validated provider record shape. Prefer authoring providers with `Provider` or the specific provider interfaces; the container owns normalized record construction. |
179
181
  | `DiErrorContext` | Structured context attached to DI errors so logs and tests can inspect tokens, scopes, modules, dependency chains, and hints. |
180
182
  | Error classes | `InvalidProviderError`, `ContainerResolutionError`, `RequestScopeResolutionError`, `ScopeMismatchError`, `CircularDependencyError`, `DuplicateProviderError`. |
@@ -1,5 +1,18 @@
1
1
  import { type Token } from '@fluojs/core';
2
- import type { Provider } from './types.js';
2
+ import type { NormalizedProvider, Provider } from './types.js';
3
+ /**
4
+ * Public read/write seam for framework-owned testing and tooling that need to
5
+ * inspect a container's resolved provider graph without depending on private
6
+ * field names or structural casts.
7
+ */
8
+ export interface ContainerResolutionState {
9
+ readonly parent?: ContainerResolutionState;
10
+ readonly registrations: Map<Token, NormalizedProvider>;
11
+ readonly multiRegistrations: Map<Token, NormalizedProvider[]>;
12
+ readonly multiSingletonCache: Map<NormalizedProvider, Promise<unknown>>;
13
+ readonly requestScopeEnabled: boolean;
14
+ readonly singletonCache: Map<Token, Promise<unknown>>;
15
+ }
3
16
  /**
4
17
  * Scope-aware dependency injection container for Fluo providers.
5
18
  */
@@ -59,6 +72,17 @@ export declare class Container {
59
72
  * @returns `true` when a single or multi provider exists for the token.
60
73
  */
61
74
  has(token: Token): boolean;
75
+ /**
76
+ * Returns the framework-owned resolution state for testing/tooling adapters.
77
+ *
78
+ * This method is the supported introspection seam for packages such as
79
+ * `@fluojs/testing`; callers should prefer ordinary `has(...)` and
80
+ * `resolve(...)` unless they need to preserve container cache ownership while
81
+ * implementing a framework-level helper.
82
+ *
83
+ * @returns Provider registrations and resolution caches for this container scope.
84
+ */
85
+ inspectResolutionState(): ContainerResolutionState;
62
86
  /**
63
87
  * Returns whether resolving a token may require a request-scope container.
64
88
  *
@@ -160,8 +184,13 @@ export declare class Container {
160
184
  private resolveProviderDependencyToken;
161
185
  private resolveForwardRefToken;
162
186
  private resolveProviderDeps;
163
- private invalidateCachedEntryInHierarchy;
187
+ private invalidateAffectedCachedEntriesInHierarchy;
164
188
  private isAncestorOf;
165
- private invalidateCachedEntry;
189
+ private invalidateAffectedCachedEntries;
190
+ private shouldInvalidateCachedToken;
191
+ private shouldInvalidateCachedProvider;
192
+ private providerDependsOnToken;
193
+ private dependencyEntryReferencesToken;
194
+ private dependencyTokenReferencesToken;
166
195
  }
167
196
  //# sourceMappingURL=container.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
package/dist/container.js CHANGED
@@ -2,6 +2,13 @@ import { InvariantError, formatTokenName } from '@fluojs/core';
2
2
  import { getClassDiMetadata } from '@fluojs/core/internal';
3
3
  import { CircularDependencyError, ContainerResolutionError, DuplicateProviderError, InvalidProviderError, RequestScopeResolutionError, ScopeMismatchError } from './errors.js';
4
4
  import { Scope, isForwardRef, isOptionalToken } from './types.js';
5
+
6
+ /**
7
+ * Public read/write seam for framework-owned testing and tooling that need to
8
+ * inspect a container's resolved provider graph without depending on private
9
+ * field names or structural casts.
10
+ */
11
+
5
12
  function isClassConstructor(value) {
6
13
  return typeof value === 'function';
7
14
  }
@@ -225,11 +232,9 @@ export class Container {
225
232
  if (!containsMultiProvider && normalizedProviders.length > 1) {
226
233
  throw new DuplicateProviderError(token);
227
234
  }
228
- const existing = this.lookupProvider(token);
229
- const existingMultiProviders = this.collectMultiProviders(token);
235
+ this.invalidateAffectedCachedEntriesInHierarchy(token);
230
236
  this.registrations.delete(token);
231
237
  this.multiRegistrations.delete(token);
232
- this.invalidateCachedEntryInHierarchy(token, existing?.scope ?? existingMultiProviders[0]?.scope ?? firstProvider.scope);
233
238
  if (containsMultiProvider) {
234
239
  this.multiRegistrations.set(token, normalizedProviders);
235
240
  this.multiOverriddenTokens.add(token);
@@ -253,6 +258,27 @@ export class Container {
253
258
  return this.lookupProvider(token) !== undefined || this.hasMulti(token);
254
259
  }
255
260
 
261
+ /**
262
+ * Returns the framework-owned resolution state for testing/tooling adapters.
263
+ *
264
+ * This method is the supported introspection seam for packages such as
265
+ * `@fluojs/testing`; callers should prefer ordinary `has(...)` and
266
+ * `resolve(...)` unless they need to preserve container cache ownership while
267
+ * implementing a framework-level helper.
268
+ *
269
+ * @returns Provider registrations and resolution caches for this container scope.
270
+ */
271
+ inspectResolutionState() {
272
+ return {
273
+ parent: this.parent?.inspectResolutionState(),
274
+ registrations: this.registrations,
275
+ multiRegistrations: this.multiRegistrations,
276
+ multiSingletonCache: this.multiSingletonCache,
277
+ requestScopeEnabled: this.requestScopeEnabled,
278
+ singletonCache: this.singletonCache
279
+ };
280
+ }
281
+
256
282
  /**
257
283
  * Returns whether resolving a token may require a request-scope container.
258
284
  *
@@ -933,15 +959,15 @@ export class Container {
933
959
  }
934
960
  return deps;
935
961
  }
936
- invalidateCachedEntryInHierarchy(token, scope) {
937
- this.invalidateCachedEntry(token, scope);
962
+ invalidateAffectedCachedEntriesInHierarchy(token) {
963
+ this.invalidateAffectedCachedEntries(token);
938
964
  const childScopes = this.root().childScopes;
939
965
  if (!childScopes) {
940
966
  return;
941
967
  }
942
968
  for (const childScope of childScopes) {
943
969
  if (this.isAncestorOf(childScope)) {
944
- childScope.invalidateCachedEntry(token, scope);
970
+ childScope.invalidateAffectedCachedEntries(token);
945
971
  }
946
972
  }
947
973
  }
@@ -955,27 +981,26 @@ export class Container {
955
981
  }
956
982
  return false;
957
983
  }
958
- invalidateCachedEntry(token, scope) {
959
- if (this.requestCache?.has(token)) {
960
- const cached = this.requestCache.get(token);
961
- if (cached) {
962
- this.scheduleStaleDisposal(cached);
984
+ invalidateAffectedCachedEntries(token) {
985
+ for (const [cachedToken, cached] of this.requestCache?.entries() ?? []) {
986
+ if (!this.shouldInvalidateCachedToken(cachedToken, token)) {
987
+ continue;
963
988
  }
964
- this.requestCache.delete(token);
989
+ this.scheduleStaleDisposal(cached);
990
+ this.requestCache?.delete(cachedToken);
965
991
  }
966
- if (!this.parent && scope === Scope.DEFAULT) {
967
- const singletonCache = this.singletonCache;
968
- if (singletonCache.has(token)) {
969
- const cached = singletonCache.get(token);
970
- if (cached) {
971
- this.scheduleStaleDisposal(cached);
992
+ if (!this.parent) {
993
+ for (const [cachedToken, cached] of this.singletonCache.entries()) {
994
+ if (!this.shouldInvalidateCachedToken(cachedToken, token)) {
995
+ continue;
972
996
  }
973
- singletonCache.delete(token);
997
+ this.scheduleStaleDisposal(cached);
998
+ this.singletonCache.delete(cachedToken);
974
999
  }
975
1000
  }
976
1001
  if (!this.parent) {
977
1002
  for (const [provider, cached] of this.multiSingletonCache.entries()) {
978
- if (provider.provide !== token) {
1003
+ if (!this.shouldInvalidateCachedProvider(provider, token)) {
979
1004
  continue;
980
1005
  }
981
1006
  this.scheduleStaleDisposal(cached);
@@ -987,11 +1012,50 @@ export class Container {
987
1012
  return;
988
1013
  }
989
1014
  for (const [provider, cached] of multiRequestCache.entries()) {
990
- if (provider.provide !== token) {
1015
+ if (!this.shouldInvalidateCachedProvider(provider, token)) {
991
1016
  continue;
992
1017
  }
993
1018
  this.scheduleStaleDisposal(cached);
994
1019
  multiRequestCache.delete(provider);
995
1020
  }
996
1021
  }
1022
+ shouldInvalidateCachedToken(cachedToken, overriddenToken) {
1023
+ if (cachedToken === overriddenToken) {
1024
+ return true;
1025
+ }
1026
+ const provider = this.lookupProvider(cachedToken);
1027
+ const multiProviders = this.collectMultiProviders(cachedToken);
1028
+ if (provider && this.providerDependsOnToken(provider, overriddenToken, new Set([provider.provide]))) {
1029
+ return true;
1030
+ }
1031
+ return multiProviders.some(multiProvider => this.providerDependsOnToken(multiProvider, overriddenToken, new Set([multiProvider.provide])));
1032
+ }
1033
+ shouldInvalidateCachedProvider(provider, overriddenToken) {
1034
+ return provider.provide === overriddenToken || this.providerDependsOnToken(provider, overriddenToken, new Set([provider.provide]));
1035
+ }
1036
+ providerDependsOnToken(provider, token, visited) {
1037
+ if (provider.type === 'existing' && provider.useExisting !== undefined) {
1038
+ return this.dependencyTokenReferencesToken(provider.useExisting, token, visited);
1039
+ }
1040
+ return provider.inject.some(depEntry => this.dependencyEntryReferencesToken(depEntry, token, visited));
1041
+ }
1042
+ dependencyEntryReferencesToken(depEntry, token, visited) {
1043
+ return this.dependencyTokenReferencesToken(this.resolveProviderDependencyToken(depEntry), token, visited);
1044
+ }
1045
+ dependencyTokenReferencesToken(depToken, token, visited) {
1046
+ if (depToken === token) {
1047
+ return true;
1048
+ }
1049
+ if (visited.has(depToken)) {
1050
+ return false;
1051
+ }
1052
+ visited.add(depToken);
1053
+ try {
1054
+ const provider = this.lookupProvider(depToken);
1055
+ const multiProviders = this.collectMultiProviders(depToken);
1056
+ return (provider ? this.providerDependsOnToken(provider, token, visited) : false) || multiProviders.some(multiProvider => this.providerDependsOnToken(multiProvider, token, visited));
1057
+ } finally {
1058
+ visited.delete(depToken);
1059
+ }
1060
+ }
997
1061
  }
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "container",
10
10
  "provider"
11
11
  ],
12
- "version": "1.0.2",
12
+ "version": "1.1.0",
13
13
  "private": false,
14
14
  "license": "MIT",
15
15
  "repository": {
@@ -36,7 +36,7 @@
36
36
  "dist"
37
37
  ],
38
38
  "dependencies": {
39
- "@fluojs/core": "^1.0.2"
39
+ "@fluojs/core": "^1.0.3"
40
40
  },
41
41
  "devDependencies": {
42
42
  "vitest": "^3.2.4"