@navios/di 0.5.0 → 0.6.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 (123) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/README.md +196 -219
  3. package/docs/README.md +69 -11
  4. package/docs/api-reference.md +281 -117
  5. package/docs/container.md +220 -56
  6. package/docs/examples/request-scope-example.mts +2 -2
  7. package/docs/factory.md +3 -8
  8. package/docs/getting-started.md +37 -8
  9. package/docs/migration.md +318 -37
  10. package/docs/request-contexts.md +263 -175
  11. package/docs/scopes.md +79 -42
  12. package/lib/browser/index.d.mts +1577 -0
  13. package/lib/browser/index.d.mts.map +1 -0
  14. package/lib/browser/index.mjs +3012 -0
  15. package/lib/browser/index.mjs.map +1 -0
  16. package/lib/index-S_qX2VLI.d.mts +1211 -0
  17. package/lib/index-S_qX2VLI.d.mts.map +1 -0
  18. package/lib/index-fKPuT65j.d.cts +1206 -0
  19. package/lib/index-fKPuT65j.d.cts.map +1 -0
  20. package/lib/index.cjs +389 -0
  21. package/lib/index.cjs.map +1 -0
  22. package/lib/index.d.cts +376 -0
  23. package/lib/index.d.cts.map +1 -0
  24. package/lib/index.d.mts +371 -78
  25. package/lib/index.d.mts.map +1 -0
  26. package/lib/index.mjs +325 -63
  27. package/lib/index.mjs.map +1 -1
  28. package/lib/testing/index.cjs +9 -0
  29. package/lib/testing/index.d.cts +2 -0
  30. package/lib/testing/index.d.mts +2 -2
  31. package/lib/testing/index.mjs +2 -72
  32. package/lib/testing-BMGmmxH7.cjs +2895 -0
  33. package/lib/testing-BMGmmxH7.cjs.map +1 -0
  34. package/lib/testing-DCXz8AJD.mjs +2655 -0
  35. package/lib/testing-DCXz8AJD.mjs.map +1 -0
  36. package/package.json +26 -4
  37. package/project.json +2 -2
  38. package/src/__tests__/async-local-storage.browser.spec.mts +240 -0
  39. package/src/__tests__/async-local-storage.spec.mts +333 -0
  40. package/src/__tests__/container.spec.mts +30 -25
  41. package/src/__tests__/e2e.browser.spec.mts +790 -0
  42. package/src/__tests__/e2e.spec.mts +1222 -0
  43. package/src/__tests__/errors.spec.mts +6 -6
  44. package/src/__tests__/factory.spec.mts +1 -1
  45. package/src/__tests__/get-injectors.spec.mts +1 -1
  46. package/src/__tests__/injectable.spec.mts +1 -1
  47. package/src/__tests__/injection-token.spec.mts +1 -1
  48. package/src/__tests__/library-findings.spec.mts +563 -0
  49. package/src/__tests__/registry.spec.mts +2 -2
  50. package/src/__tests__/request-scope.spec.mts +266 -274
  51. package/src/__tests__/service-instantiator.spec.mts +19 -17
  52. package/src/__tests__/service-locator-event-bus.spec.mts +9 -9
  53. package/src/__tests__/service-locator-manager.spec.mts +15 -15
  54. package/src/__tests__/service-locator.spec.mts +167 -244
  55. package/src/__tests__/unified-api.spec.mts +27 -27
  56. package/src/__type-tests__/factory.spec-d.mts +2 -2
  57. package/src/__type-tests__/inject.spec-d.mts +2 -2
  58. package/src/__type-tests__/injectable.spec-d.mts +1 -1
  59. package/src/browser.mts +16 -0
  60. package/src/container/container.mts +319 -0
  61. package/src/container/index.mts +2 -0
  62. package/src/container/scoped-container.mts +350 -0
  63. package/src/decorators/factory.decorator.mts +4 -4
  64. package/src/decorators/injectable.decorator.mts +5 -5
  65. package/src/errors/di-error.mts +13 -7
  66. package/src/errors/index.mts +0 -8
  67. package/src/index.mts +156 -15
  68. package/src/interfaces/container.interface.mts +82 -0
  69. package/src/interfaces/factory.interface.mts +2 -2
  70. package/src/interfaces/index.mts +1 -0
  71. package/src/internal/context/async-local-storage.mts +120 -0
  72. package/src/internal/context/factory-context.mts +18 -0
  73. package/src/internal/context/index.mts +3 -0
  74. package/src/{request-context-holder.mts → internal/context/request-context.mts} +40 -27
  75. package/src/internal/context/resolution-context.mts +63 -0
  76. package/src/internal/context/sync-local-storage.mts +51 -0
  77. package/src/internal/core/index.mts +5 -0
  78. package/src/internal/core/instance-resolver.mts +641 -0
  79. package/src/{service-instantiator.mts → internal/core/instantiator.mts} +31 -27
  80. package/src/internal/core/invalidator.mts +437 -0
  81. package/src/internal/core/service-locator.mts +202 -0
  82. package/src/{token-processor.mts → internal/core/token-processor.mts} +79 -60
  83. package/src/{base-instance-holder-manager.mts → internal/holder/base-holder-manager.mts} +91 -21
  84. package/src/internal/holder/holder-manager.mts +85 -0
  85. package/src/internal/holder/holder-storage.interface.mts +116 -0
  86. package/src/internal/holder/index.mts +6 -0
  87. package/src/internal/holder/instance-holder.mts +109 -0
  88. package/src/internal/holder/request-storage.mts +134 -0
  89. package/src/internal/holder/singleton-storage.mts +105 -0
  90. package/src/internal/index.mts +4 -0
  91. package/src/internal/lifecycle/circular-detector.mts +77 -0
  92. package/src/internal/lifecycle/index.mts +2 -0
  93. package/src/{service-locator-event-bus.mts → internal/lifecycle/lifecycle-event-bus.mts} +12 -5
  94. package/src/testing/__tests__/test-container.spec.mts +2 -2
  95. package/src/testing/test-container.mts +4 -4
  96. package/src/token/index.mts +2 -0
  97. package/src/{injection-token.mts → token/injection-token.mts} +1 -1
  98. package/src/{registry.mts → token/registry.mts} +1 -1
  99. package/src/utils/get-injectable-token.mts +1 -1
  100. package/src/utils/get-injectors.mts +32 -15
  101. package/src/utils/types.mts +1 -1
  102. package/tsdown.config.mts +67 -0
  103. package/lib/_tsup-dts-rollup.d.mts +0 -1283
  104. package/lib/_tsup-dts-rollup.d.ts +0 -1283
  105. package/lib/chunk-44F3LXW5.mjs +0 -2043
  106. package/lib/chunk-44F3LXW5.mjs.map +0 -1
  107. package/lib/index.d.ts +0 -78
  108. package/lib/index.js +0 -2127
  109. package/lib/index.js.map +0 -1
  110. package/lib/testing/index.d.ts +0 -2
  111. package/lib/testing/index.js +0 -2060
  112. package/lib/testing/index.js.map +0 -1
  113. package/lib/testing/index.mjs.map +0 -1
  114. package/src/container.mts +0 -227
  115. package/src/factory-context.mts +0 -8
  116. package/src/instance-resolver.mts +0 -559
  117. package/src/request-context-manager.mts +0 -149
  118. package/src/service-invalidator.mts +0 -429
  119. package/src/service-locator-instance-holder.mts +0 -70
  120. package/src/service-locator-manager.mts +0 -85
  121. package/src/service-locator.mts +0 -246
  122. package/tsup.config.mts +0 -12
  123. /package/src/{injector.mts → injectors.mts} +0 -0
@@ -0,0 +1,350 @@
1
+ import type { z, ZodType } from 'zod/v4'
2
+
3
+ import type { Container } from './container.mjs'
4
+ import type {
5
+ BoundInjectionToken,
6
+ ClassType,
7
+ ClassTypeWithArgument,
8
+ FactoryInjectionToken,
9
+ InjectionToken,
10
+ InjectionTokenSchemaType,
11
+ } from '../token/injection-token.mjs'
12
+ import type { IContainer } from '../interfaces/container.interface.mjs'
13
+ import type { IHolderStorage } from '../internal/holder/holder-storage.interface.mjs'
14
+ import type { Factorable } from '../interfaces/factory.interface.mjs'
15
+ import type { Registry } from '../token/registry.mjs'
16
+ import type { RequestContext } from '../internal/context/request-context.mjs'
17
+ import type { InstanceHolder } from '../internal/holder/instance-holder.mjs'
18
+ import type { Join, UnionToArray } from '../utils/types.mjs'
19
+
20
+ import { BaseHolderManager } from '../internal/holder/base-holder-manager.mjs'
21
+ import { InjectableScope } from '../enums/index.mjs'
22
+ import { DIError } from '../errors/index.mjs'
23
+ import { DefaultRequestContext } from '../internal/context/request-context.mjs'
24
+ import { RequestStorage } from '../internal/holder/request-storage.mjs'
25
+ import { InstanceStatus } from '../internal/holder/instance-holder.mjs'
26
+
27
+ /**
28
+ * Request-scoped dependency injection container.
29
+ *
30
+ * Wraps a parent Container and provides isolated request-scoped instances
31
+ * while delegating singleton and transient resolution to the parent.
32
+ * This design eliminates race conditions that can occur with async operations
33
+ * when multiple requests are processed concurrently.
34
+ */
35
+ export class ScopedContainer implements IContainer {
36
+ private readonly requestContextHolder: RequestContext
37
+ private readonly holderStorage: IHolderStorage
38
+ private disposed = false
39
+
40
+ constructor(
41
+ private readonly parent: Container,
42
+ private readonly registry: Registry,
43
+ public readonly requestId: string,
44
+ metadata?: Record<string, any>,
45
+ priority: number = 100,
46
+ ) {
47
+ this.requestContextHolder = new DefaultRequestContext(
48
+ requestId,
49
+ priority,
50
+ metadata,
51
+ )
52
+ // Create storage once and reuse for all resolutions
53
+ this.holderStorage = new RequestStorage(
54
+ this.requestContextHolder,
55
+ this.parent.getServiceLocator().getManager(),
56
+ )
57
+ }
58
+
59
+ /**
60
+ * Gets the request context holder for this scoped container.
61
+ */
62
+ getRequestContextHolder(): RequestContext {
63
+ return this.requestContextHolder
64
+ }
65
+
66
+ /**
67
+ * Gets the holder storage for this scoped container.
68
+ * Used by InstanceResolver for request-scoped resolution.
69
+ */
70
+ getHolderStorage(): IHolderStorage {
71
+ return this.holderStorage
72
+ }
73
+
74
+ /**
75
+ * Gets the request ID for this scoped container.
76
+ */
77
+ getRequestId(): string {
78
+ return this.requestId
79
+ }
80
+
81
+ /**
82
+ * Gets the parent container.
83
+ */
84
+ getParent(): Container {
85
+ return this.parent
86
+ }
87
+
88
+ /**
89
+ * Gets metadata from the request context.
90
+ */
91
+ getMetadata(key: string): any | undefined {
92
+ return this.requestContextHolder.getMetadata(key)
93
+ }
94
+
95
+ /**
96
+ * Sets metadata on the request context.
97
+ */
98
+ setMetadata(key: string, value: any): void {
99
+ this.requestContextHolder.setMetadata(key, value)
100
+ }
101
+
102
+ /**
103
+ * Adds a pre-prepared instance to the request context.
104
+ */
105
+ addInstance(token: InjectionToken<any, undefined>, instance: any): void {
106
+ this.requestContextHolder.addInstance(token, instance)
107
+ }
108
+
109
+ /**
110
+ * Gets an instance from the container.
111
+ * Request-scoped services are resolved from this container's context.
112
+ * All other services are delegated to the parent container.
113
+ */
114
+ // #1 Simple class
115
+ get<T extends ClassType>(
116
+ token: T,
117
+ ): InstanceType<T> extends Factorable<infer R>
118
+ ? Promise<R>
119
+ : Promise<InstanceType<T>>
120
+ // #1.1 Simple class with args
121
+ get<T extends ClassTypeWithArgument<R>, R>(
122
+ token: T,
123
+ args: R,
124
+ ): Promise<InstanceType<T>>
125
+ // #2 Token with required Schema
126
+ get<T, S extends InjectionTokenSchemaType>(
127
+ token: InjectionToken<T, S>,
128
+ args: z.input<S>,
129
+ ): Promise<T>
130
+ // #3 Token with optional Schema
131
+ get<T, S extends InjectionTokenSchemaType, R extends boolean>(
132
+ token: InjectionToken<T, S, R>,
133
+ ): R extends false
134
+ ? Promise<T>
135
+ : S extends ZodType<infer Type>
136
+ ? `Error: Your token requires args: ${Join<
137
+ UnionToArray<keyof Type>,
138
+ ', '
139
+ >}`
140
+ : 'Error: Your token requires args'
141
+ // #4 Token with no Schema
142
+ get<T>(token: InjectionToken<T, undefined>): Promise<T>
143
+ get<T>(token: BoundInjectionToken<T, any>): Promise<T>
144
+ get<T>(token: FactoryInjectionToken<T, any>): Promise<T>
145
+
146
+ async get(
147
+ token:
148
+ | ClassType
149
+ | InjectionToken<any>
150
+ | BoundInjectionToken<any, any>
151
+ | FactoryInjectionToken<any, any>,
152
+ args?: unknown,
153
+ ): Promise<any> {
154
+ if (this.disposed) {
155
+ throw DIError.unknown(
156
+ `ScopedContainer for request ${this.requestId} has been disposed`,
157
+ )
158
+ }
159
+
160
+ // Get the actual injection token using TokenProcessor for consistency
161
+ const tokenProcessor = this.parent.getServiceLocator().getTokenProcessor()
162
+ const actualToken = tokenProcessor.normalizeToken(token)
163
+
164
+ // Check if this is a request-scoped service
165
+ if (this.isRequestScoped(actualToken)) {
166
+ return this.resolveRequestScoped(actualToken, args)
167
+ }
168
+
169
+ // Delegate to parent for singleton/transient services
170
+ // Pass this ScopedContainer so nested inject() calls work correctly
171
+ return this.parent.getWithContext(token, args, this)
172
+ }
173
+
174
+ /**
175
+ * Invalidates a service and its dependencies.
176
+ * For request-scoped services, invalidation is handled within this context.
177
+ */
178
+ async invalidate(service: unknown): Promise<void> {
179
+ // Check if the service is in our request context
180
+ const holder = this.holderStorage.findByInstance(service)
181
+ if (holder) {
182
+ // Use the shared Invalidator with our request-scoped storage
183
+ await this.parent
184
+ .getServiceLocator()
185
+ .getInvalidator()
186
+ .invalidateWithStorage(holder.name, this.holderStorage, 1, {
187
+ emitEvents: false, // Request-scoped services don't emit global events
188
+ })
189
+ return
190
+ }
191
+
192
+ // Delegate to parent for singleton services
193
+ await this.parent.invalidate(service)
194
+ }
195
+
196
+ /**
197
+ * Checks if a service is registered.
198
+ */
199
+ isRegistered(token: any): boolean {
200
+ return this.parent.isRegistered(token)
201
+ }
202
+
203
+ /**
204
+ * Disposes this scoped container and cleans up all request-scoped instances.
205
+ * This is an alias for endRequest() for IContainer compatibility.
206
+ */
207
+ async dispose(): Promise<void> {
208
+ await this.endRequest()
209
+ }
210
+
211
+ /**
212
+ * Ends the request and cleans up all request-scoped instances.
213
+ * Uses the invalidation system to properly cascade to dependent singletons.
214
+ */
215
+ async endRequest(): Promise<void> {
216
+ if (this.disposed) {
217
+ return
218
+ }
219
+
220
+ this.disposed = true
221
+
222
+ // Use clearAllWithStorage to properly invalidate all request-scoped services
223
+ // This will cascade invalidation to singletons that depend on request-scoped services
224
+ await this.parent
225
+ .getServiceLocator()
226
+ .getInvalidator()
227
+ .clearAllWithStorage(this.holderStorage, {
228
+ waitForSettlement: true,
229
+ maxRounds: 10,
230
+ })
231
+
232
+ // Clear the context (any remaining holders that weren't invalidated)
233
+ this.requestContextHolder.clear()
234
+
235
+ // Remove from parent's active requests
236
+ this.parent.removeActiveRequest(this.requestId)
237
+ }
238
+
239
+ /**
240
+ * Waits for all pending operations to complete.
241
+ */
242
+ async ready(): Promise<void> {
243
+ await this.parent.ready()
244
+ }
245
+
246
+ /**
247
+ * @internal
248
+ * Attempts to get an instance synchronously if it already exists and is ready.
249
+ * For request-scoped services, checks this container's context first.
250
+ * For other services, delegates to the parent container.
251
+ *
252
+ * Returns null if the instance doesn't exist or is not yet ready (still creating).
253
+ */
254
+ tryGetSync<T>(token: any, args?: any): T | null {
255
+ const tokenProcessor = this.parent.getServiceLocator().getTokenProcessor()
256
+ const actualToken = tokenProcessor.normalizeToken(token)
257
+
258
+ // Check if this is a request-scoped service
259
+ if (this.isRequestScoped(actualToken)) {
260
+ const serviceLocator = this.parent.getServiceLocator()
261
+ const instanceName = serviceLocator.getInstanceIdentifier(token, args)
262
+ const holder = this.requestContextHolder.get(instanceName)
263
+ // Only return if holder exists AND is in Created status
264
+ if (
265
+ holder &&
266
+ holder.status === InstanceStatus.Created
267
+ ) {
268
+ return holder.instance as T
269
+ }
270
+ return null
271
+ }
272
+
273
+ // Delegate to parent for non-request-scoped
274
+ return this.parent.tryGetSync(token, args)
275
+ }
276
+
277
+ /**
278
+ * Checks if a token is for a request-scoped service.
279
+ */
280
+ private isRequestScoped(token: any): boolean {
281
+ // Handle BoundInjectionToken and FactoryInjectionToken using TokenProcessor
282
+ const tokenProcessor = this.parent.getServiceLocator().getTokenProcessor()
283
+ const realToken = tokenProcessor.getRealToken(token)
284
+
285
+ if (!this.registry.has(realToken)) {
286
+ return false
287
+ }
288
+
289
+ const record = this.registry.get(realToken)
290
+ return record.scope === InjectableScope.Request
291
+ }
292
+
293
+ /**
294
+ * Resolves a request-scoped service from this container's context.
295
+ * Uses locking to prevent duplicate initialization during concurrent resolution.
296
+ */
297
+ private async resolveRequestScoped(token: any, args: unknown): Promise<any> {
298
+ // Get the instance name
299
+ const serviceLocator = this.parent.getServiceLocator()
300
+ const instanceName = serviceLocator.getInstanceIdentifier(token, args)
301
+
302
+ // Check if we already have this instance (or one is being created)
303
+ const existingHolder = this.requestContextHolder.get(instanceName)
304
+ if (existingHolder) {
305
+ // Wait for the holder to be ready if it's still being created
306
+ // This prevents race conditions where multiple concurrent calls
307
+ // might try to create the same service
308
+ const [error, readyHolder] =
309
+ await BaseHolderManager.waitForHolderReady(existingHolder)
310
+ if (error) {
311
+ throw error
312
+ }
313
+ return readyHolder.instance
314
+ }
315
+
316
+ // Create new instance using parent's resolution mechanism
317
+ // but store it in our request context
318
+ return this.parent.resolveForRequest(token, args, this)
319
+ }
320
+
321
+ /**
322
+ * Stores an instance in the request context.
323
+ * Called by Container during request-scoped service resolution.
324
+ */
325
+ storeRequestInstance(
326
+ instanceName: string,
327
+ instance: any,
328
+ holder: InstanceHolder,
329
+ ): void {
330
+ this.requestContextHolder.addInstance(instanceName, instance, holder)
331
+ }
332
+
333
+ /**
334
+ * Gets an existing instance from the request context.
335
+ * Called by Container during resolution to check for existing instances.
336
+ */
337
+ getRequestInstance(
338
+ instanceName: string,
339
+ ): InstanceHolder | undefined {
340
+ return this.requestContextHolder.get(instanceName)
341
+ }
342
+
343
+ /**
344
+ * Generates a prefixed event name for request-scoped services.
345
+ * Format: {requestId}:{instanceName}
346
+ */
347
+ getPrefixedEventName(instanceName: string): string {
348
+ return `${this.requestId}:${instanceName}`
349
+ }
350
+ }
@@ -1,13 +1,13 @@
1
1
  import type {
2
2
  ClassTypeWithInstance,
3
3
  InjectionTokenSchemaType,
4
- } from '../injection-token.mjs'
4
+ } from '../token/injection-token.mjs'
5
5
  import type { Factorable, FactorableWithArgs } from '../interfaces/index.mjs'
6
- import type { Registry } from '../registry.mjs'
6
+ import type { Registry } from '../token/registry.mjs'
7
7
 
8
8
  import { InjectableScope, InjectableType } from '../enums/index.mjs'
9
- import { InjectionToken } from '../injection-token.mjs'
10
- import { globalRegistry } from '../registry.mjs'
9
+ import { InjectionToken } from '../token/injection-token.mjs'
10
+ import { globalRegistry } from '../token/registry.mjs'
11
11
  import { InjectableTokenMeta } from '../symbols/index.mjs'
12
12
 
13
13
  export interface FactoryOptions {
@@ -1,4 +1,4 @@
1
- import { z, ZodObject } from 'zod/v4'
1
+ import { z } from 'zod/v4'
2
2
 
3
3
  import type {
4
4
  BaseInjectionTokenSchemaType,
@@ -11,12 +11,12 @@ import type {
11
11
  ClassTypeWithoutArguments,
12
12
  InjectionTokenSchemaType,
13
13
  OptionalInjectionTokenSchemaType,
14
- } from '../injection-token.mjs'
15
- import type { Registry } from '../registry.mjs'
14
+ } from '../token/injection-token.mjs'
15
+ import type { Registry } from '../token/registry.mjs'
16
16
 
17
17
  import { InjectableScope, InjectableType } from '../enums/index.mjs'
18
- import { InjectionToken } from '../injection-token.mjs'
19
- import { globalRegistry } from '../registry.mjs'
18
+ import { InjectionToken } from '../token/injection-token.mjs'
19
+ import { globalRegistry } from '../token/registry.mjs'
20
20
  import { InjectableTokenMeta } from '../symbols/index.mjs'
21
21
 
22
22
  export interface InjectableOptions {
@@ -3,21 +3,18 @@ export enum DIErrorCode {
3
3
  FactoryTokenNotResolved = 'FactoryTokenNotResolved',
4
4
  InstanceNotFound = 'InstanceNotFound',
5
5
  InstanceDestroying = 'InstanceDestroying',
6
+ CircularDependency = 'CircularDependency',
6
7
  UnknownError = 'UnknownError',
7
8
  }
8
9
 
9
- export class DIError extends Error {
10
- public readonly code: DIErrorCode
10
+ export class DIError {
11
11
  public readonly context?: Record<string, unknown>
12
12
 
13
13
  constructor(
14
- code: DIErrorCode,
15
- message: string,
14
+ public readonly code: DIErrorCode,
15
+ public readonly message: string,
16
16
  context?: Record<string, unknown>,
17
17
  ) {
18
- super(message)
19
- this.name = 'DIError'
20
- this.code = code
21
18
  this.context = context
22
19
  }
23
20
 
@@ -66,4 +63,13 @@ export class DIError extends Error {
66
63
  }
67
64
  return new DIError(DIErrorCode.UnknownError, message, context)
68
65
  }
66
+
67
+ static circularDependency(cycle: string[]): DIError {
68
+ const cycleStr = cycle.join(' -> ')
69
+ return new DIError(
70
+ DIErrorCode.CircularDependency,
71
+ `Circular dependency detected: ${cycleStr}`,
72
+ { cycle },
73
+ )
74
+ }
69
75
  }
@@ -1,9 +1 @@
1
1
  export * from './di-error.mjs'
2
-
3
- // Legacy exports for backward compatibility (deprecated)
4
- export { DIError as FactoryNotFound } from './di-error.mjs'
5
- export { DIError as FactoryTokenNotResolved } from './di-error.mjs'
6
- export { DIError as InstanceDestroying } from './di-error.mjs'
7
- export { DIError as InstanceNotFound } from './di-error.mjs'
8
- export { DIError as UnknownError } from './di-error.mjs'
9
- export { DIErrorCode as ErrorsEnum } from './di-error.mjs'
package/src/index.mts CHANGED
@@ -1,19 +1,160 @@
1
+ /**
2
+ * @navios/di - Dependency Injection Library
3
+ *
4
+ * This library provides a flexible dependency injection system with support for:
5
+ * - Singleton and request-scoped services
6
+ * - Factory-based and class-based service instantiation
7
+ * - Circular dependency detection
8
+ * - Schema validation for service arguments
9
+ * - Lifecycle hooks (onServiceInit, onServiceDestroy)
10
+ */
11
+
12
+ // ============================================================================
13
+ // PUBLIC API - Container
14
+ // ============================================================================
15
+
16
+ export { Container } from './container/container.mjs'
17
+ export { ScopedContainer } from './container/scoped-container.mjs'
18
+
19
+ // ============================================================================
20
+ // PUBLIC API - Tokens
21
+ // ============================================================================
22
+
23
+ export {
24
+ InjectionToken,
25
+ BoundInjectionToken,
26
+ FactoryInjectionToken,
27
+ type ClassType,
28
+ type ClassTypeWithoutArguments,
29
+ type ClassTypeWithArgument,
30
+ type ClassTypeWithOptionalArgument,
31
+ type ClassTypeWithInstance,
32
+ type ClassTypeWithInstanceAndArgument,
33
+ type ClassTypeWithInstanceAndOptionalArgument,
34
+ type AnyInjectableType,
35
+ type InjectionTokenType,
36
+ type InjectionTokenSchemaType,
37
+ } from './token/injection-token.mjs'
38
+
39
+ export { Registry, globalRegistry, type FactoryRecord } from './token/registry.mjs'
40
+
41
+ // ============================================================================
42
+ // PUBLIC API - Decorators
43
+ // ============================================================================
44
+
1
45
  export * from './decorators/index.mjs'
46
+
47
+ // ============================================================================
48
+ // PUBLIC API - Enums
49
+ // ============================================================================
50
+
2
51
  export * from './enums/index.mjs'
3
- export * from './errors/index.mjs'
52
+
53
+ // ============================================================================
54
+ // PUBLIC API - Interfaces
55
+ // ============================================================================
56
+
4
57
  export * from './interfaces/index.mjs'
58
+
59
+ // ============================================================================
60
+ // PUBLIC API - Errors
61
+ // ============================================================================
62
+
63
+ export * from './errors/index.mjs'
64
+
65
+ // ============================================================================
66
+ // PUBLIC API - Utilities
67
+ // ============================================================================
68
+
5
69
  export * from './utils/index.mjs'
6
- export * from './base-instance-holder-manager.mjs'
7
- export * from './event-emitter.mjs'
8
- export * from './factory-context.mjs'
9
- export * from './injection-token.mjs'
10
- export * from './injector.mjs'
11
- export * from './registry.mjs'
12
- export * from './service-instantiator.mjs'
13
- export * from './service-locator.mjs'
14
- export * from './service-locator-event-bus.mjs'
15
- export * from './service-locator-instance-holder.mjs'
16
- export * from './service-locator-manager.mjs'
17
- export * from './request-context-holder.mjs'
18
- export * from './symbols/injectable-token.mjs'
19
- export * from './container.mjs'
70
+
71
+ // ============================================================================
72
+ // PUBLIC API - Symbols
73
+ // ============================================================================
74
+
75
+ export * from './symbols/index.mjs'
76
+
77
+ // ============================================================================
78
+ // PUBLIC API - Event Emitter
79
+ // ============================================================================
80
+
81
+ export { EventEmitter } from './event-emitter.mjs'
82
+
83
+ // ============================================================================
84
+ // PUBLIC API - Injectors
85
+ // ============================================================================
86
+
87
+ export {
88
+ defaultInjectors,
89
+ asyncInject,
90
+ inject,
91
+ optional,
92
+ wrapSyncInit,
93
+ provideFactoryContext,
94
+ } from './injectors.mjs'
95
+
96
+ // ============================================================================
97
+ // PUBLIC API - Testing
98
+ // ============================================================================
99
+
100
+ export * from './testing/index.mjs'
101
+
102
+ // ============================================================================
103
+ // INTERNAL API (exported for advanced use cases)
104
+ // ============================================================================
105
+
106
+ // Context types
107
+ export type { FactoryContext } from './internal/context/factory-context.mjs'
108
+ export {
109
+ type RequestContext,
110
+ type RequestContextHolder,
111
+ DefaultRequestContext,
112
+ createRequestContext,
113
+ } from './internal/context/request-context.mjs'
114
+ export {
115
+ type ResolutionContextData,
116
+ resolutionContext,
117
+ withResolutionContext,
118
+ getCurrentResolutionContext,
119
+ withoutResolutionContext,
120
+ } from './internal/context/resolution-context.mjs'
121
+
122
+ // Holder types
123
+ export {
124
+ InstanceStatus,
125
+ type InstanceHolder,
126
+ type InstanceEffect,
127
+ type InstanceDestroyListener,
128
+ type InstanceHolderCreating,
129
+ type InstanceHolderCreated,
130
+ type InstanceHolderDestroying,
131
+ type InstanceHolderError,
132
+ } from './internal/holder/instance-holder.mjs'
133
+
134
+ export {
135
+ BaseHolderManager,
136
+ type HolderReadyResult,
137
+ } from './internal/holder/base-holder-manager.mjs'
138
+
139
+ export { HolderManager } from './internal/holder/holder-manager.mjs'
140
+
141
+ export {
142
+ type HolderGetResult,
143
+ type IHolderStorage,
144
+ } from './internal/holder/holder-storage.interface.mjs'
145
+
146
+ export { SingletonStorage } from './internal/holder/singleton-storage.mjs'
147
+
148
+ export { RequestStorage } from './internal/holder/request-storage.mjs'
149
+
150
+ // Lifecycle
151
+ export { LifecycleEventBus } from './internal/lifecycle/lifecycle-event-bus.mjs'
152
+
153
+ export { CircularDetector } from './internal/lifecycle/circular-detector.mjs'
154
+
155
+ // Core engine
156
+ export { ServiceLocator } from './internal/core/service-locator.mjs'
157
+ export { InstanceResolver } from './internal/core/instance-resolver.mjs'
158
+ export { Instantiator } from './internal/core/instantiator.mjs'
159
+ export { Invalidator } from './internal/core/invalidator.mjs'
160
+ export { TokenProcessor } from './internal/core/token-processor.mjs'