@djodjonx/wiredi 0.0.2

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 (37) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +516 -0
  3. package/dist/index.cjs +931 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +1139 -0
  6. package/dist/index.d.cts.map +1 -0
  7. package/dist/index.d.mts +1139 -0
  8. package/dist/index.d.mts.map +1 -0
  9. package/dist/index.mjs +915 -0
  10. package/dist/index.mjs.map +1 -0
  11. package/dist/plugin/ConfigurationAnalyzer.d.ts +59 -0
  12. package/dist/plugin/ConfigurationAnalyzer.d.ts.map +1 -0
  13. package/dist/plugin/ConfigurationAnalyzer.js +321 -0
  14. package/dist/plugin/ConfigurationAnalyzer.js.map +1 -0
  15. package/dist/plugin/DependencyAnalyzer.d.ts +54 -0
  16. package/dist/plugin/DependencyAnalyzer.d.ts.map +1 -0
  17. package/dist/plugin/DependencyAnalyzer.js +208 -0
  18. package/dist/plugin/DependencyAnalyzer.js.map +1 -0
  19. package/dist/plugin/TokenNormalizer.d.ts +51 -0
  20. package/dist/plugin/TokenNormalizer.d.ts.map +1 -0
  21. package/dist/plugin/TokenNormalizer.js +208 -0
  22. package/dist/plugin/TokenNormalizer.js.map +1 -0
  23. package/dist/plugin/ValidationEngine.d.ts +53 -0
  24. package/dist/plugin/ValidationEngine.d.ts.map +1 -0
  25. package/dist/plugin/ValidationEngine.js +250 -0
  26. package/dist/plugin/ValidationEngine.js.map +1 -0
  27. package/dist/plugin/index.d.ts +2 -0
  28. package/dist/plugin/index.d.ts.map +1 -0
  29. package/dist/plugin/index.js +144 -0
  30. package/dist/plugin/index.js.map +1 -0
  31. package/dist/plugin/package.json +6 -0
  32. package/dist/plugin/types.d.ts +152 -0
  33. package/dist/plugin/types.d.ts.map +1 -0
  34. package/dist/plugin/types.js +3 -0
  35. package/dist/plugin/types.js.map +1 -0
  36. package/package.json +95 -0
  37. package/plugin.js +1 -0
@@ -0,0 +1,1139 @@
1
+ import * as awilix0 from "awilix";
2
+ import { AwilixContainer } from "awilix";
3
+ import * as inversify0 from "inversify";
4
+ import { Container } from "inversify";
5
+
6
+ //#region src/Provider/types.d.ts
7
+ /**
8
+ * Generic constructor type
9
+ * @template T - The type of the class instance
10
+ */
11
+ type Constructor$3<T = any> = new (...args: any[]) => T;
12
+ /**
13
+ * Dependency lifecycle options
14
+ * Independent of the underlying container implementation
15
+ */
16
+ declare enum ProviderLifecycle {
17
+ /** Single shared instance throughout the application (default) */
18
+ Singleton = "singleton",
19
+ /** New instance created on each resolution */
20
+ Transient = "transient",
21
+ /** One instance per scope/child container */
22
+ Scoped = "scoped",
23
+ }
24
+ /**
25
+ * Resolution token type (symbol or class constructor)
26
+ * @template T - The type of the resolved dependency
27
+ */
28
+ type ProviderToken<T = any> = symbol | Constructor$3<T>;
29
+ /**
30
+ * DI Container Provider Interface
31
+ *
32
+ * Contract that each adapter (tsyringe, awilix, inversify, etc.)
33
+ * must implement to be compatible with WireDI.
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * class MyCustomProvider implements ContainerProvider {
38
+ * readonly name = 'my-provider'
39
+ * // ... implement all methods
40
+ * }
41
+ * ```
42
+ */
43
+ interface ContainerProvider {
44
+ /**
45
+ * Provider name for debugging and logging purposes
46
+ */
47
+ readonly name: string;
48
+ /**
49
+ * Registers a static value in the container
50
+ *
51
+ * @template T - The type of the value
52
+ * @param token - Symbol token to register the value under
53
+ * @param value - The value to register
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * provider.registerValue(TOKENS.ApiUrl, 'https://api.example.com')
58
+ * ```
59
+ */
60
+ registerValue<T>(token: symbol, value: T): void;
61
+ /**
62
+ * Registers a factory function in the container
63
+ *
64
+ * @template T - The type of the value produced by the factory
65
+ * @param token - Symbol token to register the factory under
66
+ * @param factory - Function that creates the instance (receives the provider to resolve dependencies)
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * provider.registerFactory(TOKENS.HttpClient, (p) => {
71
+ * return new HttpClient(p.resolve(TOKENS.ApiUrl))
72
+ * })
73
+ * ```
74
+ */
75
+ registerFactory<T>(token: symbol, factory: (provider: ContainerProvider) => T): void;
76
+ /**
77
+ * Registers a class in the container
78
+ *
79
+ * @template T - The type of the class instance
80
+ * @param token - Token (symbol or class) to register under
81
+ * @param implementation - Class to instantiate (optional if token is a class)
82
+ * @param lifecycle - Instance lifecycle (Singleton, Transient, or Scoped)
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * // Register class as its own token
87
+ * provider.registerClass(UserService)
88
+ *
89
+ * // Register implementation for a symbol token
90
+ * provider.registerClass(TOKENS.Logger, ConsoleLogger, ProviderLifecycle.Singleton)
91
+ * ```
92
+ */
93
+ registerClass<T>(token: ProviderToken<T>, implementation?: Constructor$3<T>, lifecycle?: ProviderLifecycle): void;
94
+ /**
95
+ * Checks if a token is already registered in the container
96
+ *
97
+ * @param token - Token to check
98
+ * @returns `true` if the token is registered, `false` otherwise
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * if (!provider.isRegistered(TOKENS.Logger)) {
103
+ * provider.registerClass(TOKENS.Logger, ConsoleLogger)
104
+ * }
105
+ * ```
106
+ */
107
+ isRegistered(token: ProviderToken): boolean;
108
+ /**
109
+ * Resolves a dependency from the container
110
+ *
111
+ * @template T - The type of the resolved dependency
112
+ * @param token - Token of the dependency to resolve
113
+ * @returns Instance of the dependency
114
+ * @throws Error if the token is not registered
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * const logger = provider.resolve<LoggerInterface>(TOKENS.Logger)
119
+ * const userService = provider.resolve(UserService)
120
+ * ```
121
+ */
122
+ resolve<T>(token: ProviderToken<T>): T;
123
+ /**
124
+ * Creates a child scope (child container)
125
+ * Useful for HTTP requests, transactions, or isolated contexts
126
+ *
127
+ * @returns New scoped provider instance
128
+ *
129
+ * @example
130
+ * ```typescript
131
+ * const requestScope = provider.createScope()
132
+ * requestScope.registerValue(TOKENS.RequestId, generateRequestId())
133
+ * ```
134
+ */
135
+ createScope(): ContainerProvider;
136
+ /**
137
+ * Releases provider resources
138
+ * Called during application cleanup or shutdown
139
+ */
140
+ dispose(): void;
141
+ /**
142
+ * Access to the underlying container (for advanced use cases)
143
+ * Return type is generic as it depends on the implementation
144
+ *
145
+ * @returns The underlying DI container instance
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * const tsyringeContainer = provider.getUnderlyingContainer() as DependencyContainer
150
+ * ```
151
+ */
152
+ getUnderlyingContainer(): unknown;
153
+ }
154
+ /**
155
+ * Options for provider adapters
156
+ */
157
+ interface ProviderAdapterOptions {
158
+ /**
159
+ * Existing container to use (optional)
160
+ * If not provided, a new container will be created
161
+ */
162
+ container?: unknown;
163
+ }
164
+ //#endregion
165
+ //#region src/Provider/ProviderManager.d.ts
166
+ /**
167
+ * Configures the DI container provider to use globally
168
+ *
169
+ * Must be called ONCE at the application entry point,
170
+ * before any calls to `useBuilder`.
171
+ *
172
+ * @param provider - The provider instance to use
173
+ * @throws Error if a provider is already configured
174
+ *
175
+ * @example
176
+ * ```typescript
177
+ * // main.ts - Application entry point
178
+ * import 'reflect-metadata'
179
+ * import { container, Lifecycle } from 'tsyringe'
180
+ * import { useContainerProvider, TsyringeProvider } from '@djodjonx/wiredi'
181
+ *
182
+ * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))
183
+ *
184
+ * // Now useBuilder can be used anywhere
185
+ * ```
186
+ */
187
+ declare function useContainerProvider(provider: ContainerProvider): void;
188
+ /**
189
+ * Retrieves the configured container provider
190
+ *
191
+ * @returns The configured provider instance
192
+ * @throws Error if no provider is configured
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * const provider = getContainerProvider()
197
+ * const service = provider.resolve(MyService)
198
+ * ```
199
+ */
200
+ declare function getContainerProvider(): ContainerProvider;
201
+ /**
202
+ * Checks if a provider is currently configured
203
+ *
204
+ * @returns `true` if a provider is configured, `false` otherwise
205
+ *
206
+ * @example
207
+ * ```typescript
208
+ * if (!hasContainerProvider()) {
209
+ * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))
210
+ * }
211
+ * ```
212
+ */
213
+ declare function hasContainerProvider(): boolean;
214
+ /**
215
+ * Resets the global provider (primarily for testing)
216
+ *
217
+ * ⚠️ WARNING: Do not use in production, only for testing purposes
218
+ *
219
+ * @example
220
+ * ```typescript
221
+ * // In a test file
222
+ * beforeEach(() => {
223
+ * resetContainerProvider()
224
+ * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))
225
+ * })
226
+ * ```
227
+ */
228
+ declare function resetContainerProvider(): void;
229
+ //#endregion
230
+ //#region src/Provider/adapters/TsyringeProvider.d.ts
231
+ /**
232
+ * Minimal interface for tsyringe's DependencyContainer
233
+ * Allows decoupling from the actual tsyringe package
234
+ */
235
+ interface TsyringeDependencyContainer {
236
+ /**
237
+ * Registers a dependency in the container
238
+ */
239
+ register<T>(token: any, provider: {
240
+ useValue?: T;
241
+ useFactory?: () => T;
242
+ useClass?: Constructor$3<T>;
243
+ }, options?: {
244
+ lifecycle?: unknown;
245
+ }): void;
246
+ /**
247
+ * Checks if a token is registered
248
+ */
249
+ isRegistered(token: any): boolean;
250
+ /**
251
+ * Resolves a dependency from the container
252
+ */
253
+ resolve<T>(token: any): T;
254
+ /**
255
+ * Creates a child container for scoped registrations
256
+ */
257
+ createChildContainer(): TsyringeDependencyContainer;
258
+ /**
259
+ * Clears all singleton instances
260
+ */
261
+ clearInstances(): void;
262
+ }
263
+ /**
264
+ * Minimal interface for tsyringe's Lifecycle enum
265
+ */
266
+ interface TsyringeLifecycle {
267
+ /** Single instance throughout the application */
268
+ Singleton: unknown;
269
+ /** New instance on each resolution */
270
+ Transient: unknown;
271
+ /** Single instance per child container */
272
+ ContainerScoped: unknown;
273
+ /** Single instance per resolution tree */
274
+ ResolutionScoped: unknown;
275
+ }
276
+ /**
277
+ * Dependencies required to create a TsyringeProvider
278
+ * The user must provide these from their tsyringe installation
279
+ */
280
+ interface TsyringeDependencies {
281
+ /**
282
+ * The tsyringe container to use
283
+ * @example `import { container } from 'tsyringe'`
284
+ */
285
+ container: TsyringeDependencyContainer;
286
+ /**
287
+ * The tsyringe Lifecycle enum
288
+ * @example `import { Lifecycle } from 'tsyringe'`
289
+ */
290
+ Lifecycle: TsyringeLifecycle;
291
+ }
292
+ /**
293
+ * Configuration options for TsyringeProvider
294
+ */
295
+ interface TsyringeProviderOptions {
296
+ /**
297
+ * Use a child container instead of the provided container
298
+ * Useful for isolating registrations in tests or modules
299
+ * @default false
300
+ */
301
+ useChildContainer?: boolean;
302
+ }
303
+ /**
304
+ * tsyringe adapter implementing the ContainerProvider interface
305
+ *
306
+ * Provides integration between WireDI and tsyringe,
307
+ * allowing you to use tsyringe as your DI container while benefiting
308
+ * from WireDI's configuration and validation features.
309
+ */
310
+ declare class TsyringeProvider implements ContainerProvider {
311
+ /** @inheritdoc */
312
+ readonly name = "tsyringe";
313
+ /** The tsyringe container instance */
314
+ private readonly container;
315
+ /** The tsyringe Lifecycle enum reference */
316
+ private readonly Lifecycle;
317
+ /**
318
+ * Creates a new TsyringeProvider instance
319
+ *
320
+ * @param dependencies - tsyringe dependencies (container and Lifecycle)
321
+ * @param options - Configuration options
322
+ *
323
+ * @example
324
+ * ```typescript
325
+ * import { container, Lifecycle } from 'tsyringe'
326
+ *
327
+ * const provider = new TsyringeProvider(
328
+ * { container, Lifecycle },
329
+ * { useChildContainer: true }
330
+ * )
331
+ * ```
332
+ */
333
+ constructor(dependencies: TsyringeDependencies, options?: TsyringeProviderOptions);
334
+ /** @inheritdoc */
335
+ registerValue<T>(token: symbol, value: T): void;
336
+ /** @inheritdoc */
337
+ registerFactory<T>(token: symbol, factory: (provider: ContainerProvider) => T): void;
338
+ /** @inheritdoc */
339
+ registerClass<T>(token: ProviderToken<T>, implementation?: Constructor$3<T>, lifecycle?: ProviderLifecycle): void;
340
+ /** @inheritdoc */
341
+ isRegistered(token: ProviderToken): boolean;
342
+ /** @inheritdoc */
343
+ resolve<T>(token: ProviderToken<T>): T;
344
+ /** @inheritdoc */
345
+ createScope(): ContainerProvider;
346
+ /** @inheritdoc */
347
+ dispose(): void;
348
+ /**
349
+ * Returns the underlying tsyringe DependencyContainer
350
+ * @returns The tsyringe container instance
351
+ */
352
+ getUnderlyingContainer(): TsyringeDependencyContainer;
353
+ /**
354
+ * Maps WireDI lifecycle to tsyringe Lifecycle
355
+ * @internal
356
+ */
357
+ private mapLifecycle;
358
+ /**
359
+ * Type guard to check if a token is a class constructor
360
+ * @internal
361
+ */
362
+ private isConstructor;
363
+ }
364
+ //#endregion
365
+ //#region src/Provider/adapters/AwilixProvider.d.ts
366
+ /**
367
+ * Generic constructor type for class instantiation
368
+ * @template T - The type of the class instance
369
+ * @internal
370
+ */
371
+ type Constructor$2<T = any> = new (...args: any[]) => T;
372
+ /**
373
+ * Configuration options for AwilixProvider
374
+ */
375
+ interface AwilixProviderOptions {
376
+ /**
377
+ * Existing Awilix container to use
378
+ * If not provided, a new container will be created
379
+ * @default undefined (creates new container)
380
+ */
381
+ container?: AwilixContainer;
382
+ /**
383
+ * Awilix injection mode
384
+ * - `'PROXY'`: Dependencies are injected via a proxy object (recommended)
385
+ * - `'CLASSIC'`: Dependencies are injected via constructor parameters by name
386
+ * @default 'PROXY'
387
+ */
388
+ injectionMode?: 'PROXY' | 'CLASSIC';
389
+ }
390
+ /**
391
+ * Awilix adapter implementing the ContainerProvider interface
392
+ *
393
+ * Provides integration between WireDI and Awilix,
394
+ * allowing you to use Awilix as your DI container while benefiting
395
+ * from WireDI's configuration and validation features.
396
+ */
397
+ declare class AwilixProvider implements ContainerProvider {
398
+ private options;
399
+ /** @inheritdoc */
400
+ readonly name = "awilix";
401
+ /** The Awilix container instance */
402
+ private container;
403
+ /** Maps tokens to Awilix string-based registration names */
404
+ private tokenToName;
405
+ /** Counter for generating unique token names */
406
+ private nameCounter;
407
+ /** Lazily loaded awilix module */
408
+ private awilix;
409
+ /**
410
+ * Creates a new AwilixProvider instance
411
+ *
412
+ * @param options - Configuration options
413
+ *
414
+ * @remarks
415
+ * When using the constructor directly, you must call `init()` before use,
416
+ * or use `createSync()` for synchronous initialization.
417
+ */
418
+ constructor(options?: AwilixProviderOptions);
419
+ /**
420
+ * Lazily initializes the container (async)
421
+ * @internal
422
+ */
423
+ private ensureInitialized;
424
+ /**
425
+ * Throws if container is not initialized
426
+ * @internal
427
+ */
428
+ private ensureInitializedSync;
429
+ /**
430
+ * Initializes the provider asynchronously
431
+ *
432
+ * @remarks
433
+ * Required before using the provider if not using `createSync()`.
434
+ *
435
+ * @example
436
+ * ```typescript
437
+ * const provider = new AwilixProvider({ injectionMode: 'PROXY' })
438
+ * await provider.init()
439
+ * useContainerProvider(provider)
440
+ * ```
441
+ */
442
+ init(): Promise<void>;
443
+ /**
444
+ * Creates a pre-initialized provider synchronously
445
+ *
446
+ * @param awilix - The awilix module import
447
+ * @param options - Configuration options
448
+ * @returns Fully initialized AwilixProvider instance
449
+ *
450
+ * @remarks
451
+ * This is the recommended way to create an AwilixProvider as it
452
+ * avoids async initialization and ensures the provider is ready immediately.
453
+ *
454
+ * @example
455
+ * ```typescript
456
+ * import * as awilix from 'awilix'
457
+ *
458
+ * const provider = AwilixProvider.createSync(awilix, {
459
+ * injectionMode: 'CLASSIC'
460
+ * })
461
+ * ```
462
+ */
463
+ static createSync(awilix: typeof awilix0, options?: AwilixProviderOptions): AwilixProvider;
464
+ /**
465
+ * Gets or creates a unique string name for a token
466
+ * Awilix uses string-based registration, so we map symbols/classes to strings
467
+ * @internal
468
+ */
469
+ private getTokenName;
470
+ /**
471
+ * Maps WireDI lifecycle to Awilix Lifetime
472
+ * @internal
473
+ */
474
+ private mapLifecycle;
475
+ /** @inheritdoc */
476
+ registerValue<T>(token: symbol, value: T): void;
477
+ /** @inheritdoc */
478
+ registerFactory<T>(token: symbol, factory: (provider: ContainerProvider) => T): void;
479
+ /** @inheritdoc */
480
+ registerClass<T>(token: symbol | Constructor$2<T>, impl?: Constructor$2<T>, lifecycle?: ProviderLifecycle): void;
481
+ /** @inheritdoc */
482
+ isRegistered(token: symbol | Constructor$2): boolean;
483
+ /** @inheritdoc */
484
+ resolve<T>(token: symbol | Constructor$2<T>): T;
485
+ /** @inheritdoc */
486
+ createScope(): ContainerProvider;
487
+ /** @inheritdoc */
488
+ dispose(): void;
489
+ /**
490
+ * Returns the underlying Awilix container instance
491
+ * @returns The AwilixContainer instance
492
+ */
493
+ getUnderlyingContainer(): AwilixContainer;
494
+ }
495
+ //#endregion
496
+ //#region src/Provider/adapters/InversifyProvider.d.ts
497
+ /**
498
+ * Generic constructor type for class instantiation
499
+ * @template T - The type of the class instance
500
+ * @internal
501
+ */
502
+ type Constructor$1<T = any> = new (...args: any[]) => T;
503
+ /**
504
+ * InversifyJS binding scope options
505
+ * @internal
506
+ */
507
+ type BindingScope = 'Singleton' | 'Transient' | 'Request';
508
+ /**
509
+ * Configuration options for InversifyProvider
510
+ */
511
+ interface InversifyProviderOptions {
512
+ /**
513
+ * Existing Inversify container to use
514
+ * If not provided, a new container will be created
515
+ * @default undefined (creates new container)
516
+ */
517
+ container?: Container;
518
+ /**
519
+ * Default binding scope for registrations without explicit lifecycle
520
+ * @default 'Singleton'
521
+ */
522
+ defaultScope?: BindingScope;
523
+ }
524
+ /**
525
+ * InversifyJS adapter implementing the ContainerProvider interface
526
+ *
527
+ * Provides integration between WireDI and InversifyJS,
528
+ * allowing you to use InversifyJS as your DI container while benefiting
529
+ * from WireDI's configuration and validation features.
530
+ */
531
+ declare class InversifyProvider implements ContainerProvider {
532
+ private options;
533
+ /** @inheritdoc */
534
+ readonly name = "inversify";
535
+ /** The InversifyJS container instance */
536
+ private container;
537
+ /** Default scope for bindings */
538
+ private defaultScope;
539
+ /** Lazily loaded inversify module */
540
+ private inversify;
541
+ /**
542
+ * Creates a new InversifyProvider instance
543
+ *
544
+ * @param options - Configuration options
545
+ *
546
+ * @remarks
547
+ * When using the constructor directly, you must call `init()` before use,
548
+ * or use `createSync()` for synchronous initialization.
549
+ */
550
+ constructor(options?: InversifyProviderOptions);
551
+ /**
552
+ * Lazily initializes the container (async)
553
+ * @internal
554
+ */
555
+ private ensureInitialized;
556
+ /**
557
+ * Throws if container is not initialized
558
+ * @internal
559
+ */
560
+ private ensureInitializedSync;
561
+ /**
562
+ * Initializes the provider asynchronously
563
+ *
564
+ * @remarks
565
+ * Required before using the provider if not using `createSync()`.
566
+ *
567
+ * @example
568
+ * ```typescript
569
+ * const provider = new InversifyProvider()
570
+ * await provider.init()
571
+ * useContainerProvider(provider)
572
+ * ```
573
+ */
574
+ init(): Promise<void>;
575
+ /**
576
+ * Creates a pre-initialized provider synchronously
577
+ *
578
+ * @param inversify - The inversify module import
579
+ * @param options - Configuration options
580
+ * @returns Fully initialized InversifyProvider instance
581
+ *
582
+ * @remarks
583
+ * This is the recommended way to create an InversifyProvider as it
584
+ * avoids async initialization and ensures the provider is ready immediately.
585
+ *
586
+ * @example
587
+ * ```typescript
588
+ * import * as inversify from 'inversify'
589
+ *
590
+ * const provider = InversifyProvider.createSync(inversify, {
591
+ * defaultScope: 'Transient'
592
+ * })
593
+ * ```
594
+ */
595
+ static createSync(inversify: typeof inversify0, options?: InversifyProviderOptions): InversifyProvider;
596
+ /**
597
+ * Maps WireDI lifecycle to InversifyJS binding scope
598
+ * @internal
599
+ */
600
+ private mapLifecycle;
601
+ /**
602
+ * Applies the scope to an InversifyJS binding
603
+ * @internal
604
+ */
605
+ private applyScope;
606
+ /** @inheritdoc */
607
+ registerValue<T>(token: symbol, value: T): void;
608
+ /** @inheritdoc */
609
+ registerFactory<T>(token: symbol, factory: (provider: ContainerProvider) => T): void;
610
+ /** @inheritdoc */
611
+ registerClass<T>(token: symbol | Constructor$1<T>, impl?: Constructor$1<T>, lifecycle?: ProviderLifecycle): void;
612
+ /** @inheritdoc */
613
+ isRegistered(token: symbol | Constructor$1): boolean;
614
+ /** @inheritdoc */
615
+ resolve<T>(token: symbol | Constructor$1<T>): T;
616
+ /** @inheritdoc */
617
+ createScope(): ContainerProvider;
618
+ /** @inheritdoc */
619
+ dispose(): void;
620
+ /**
621
+ * Returns the underlying InversifyJS Container instance
622
+ * @returns The InversifyJS Container
623
+ */
624
+ getUnderlyingContainer(): Container;
625
+ }
626
+ //#endregion
627
+ //#region src/EventDispatcher/Provider/types.d.ts
628
+ /**
629
+ * Token representing an event type (class constructor)
630
+ * Events are identified by their class constructor
631
+ */
632
+ type EventToken = new (...args: any[]) => any;
633
+ /**
634
+ * Token representing a listener (class constructor or symbol)
635
+ * Listeners can be registered as classes or symbol tokens
636
+ */
637
+ type ListenerToken = (new (...args: any[]) => any) | symbol;
638
+ /**
639
+ * Configuration entry for registering a listener to an event
640
+ *
641
+ * @example
642
+ * ```typescript
643
+ * const entry: EventListenerEntry = {
644
+ * event: UserCreatedEvent,
645
+ * listener: SendWelcomeEmailListener
646
+ * }
647
+ * ```
648
+ */
649
+ interface EventListenerEntry {
650
+ /** The event class to listen for */
651
+ event: EventToken;
652
+ /** The listener class or token to invoke */
653
+ listener: ListenerToken;
654
+ }
655
+ /**
656
+ * Interface for Event Dispatcher Provider
657
+ *
658
+ * This abstraction allows plugging different event dispatching systems
659
+ * (e.g., custom implementation, EventEmitter, RxJS, etc.)
660
+ *
661
+ * @example
662
+ * ```typescript
663
+ * // Create and register provider at app startup
664
+ * const eventProvider = new MutableEventDispatcherProvider({
665
+ * containerProvider: getContainerProvider()
666
+ * })
667
+ * useEventDispatcherProvider(eventProvider)
668
+ *
669
+ * // Later, dispatch events
670
+ * const dispatcher = getEventDispatcherProvider()
671
+ * dispatcher.dispatch(new UserCreatedEvent(user))
672
+ * ```
673
+ */
674
+ interface EventDispatcherProvider {
675
+ /**
676
+ * Unique name identifying this provider implementation
677
+ * Used for debugging and logging purposes
678
+ */
679
+ readonly name: string;
680
+ /**
681
+ * Registers a listener for a specific event type
682
+ *
683
+ * @param eventToken - The event class/constructor to listen for
684
+ * @param listenerToken - The listener class/symbol to invoke when event is dispatched
685
+ *
686
+ * @example
687
+ * ```typescript
688
+ * provider.register(UserCreatedEvent, SendWelcomeEmailListener)
689
+ * ```
690
+ */
691
+ register(eventToken: EventToken, listenerToken: ListenerToken): void;
692
+ /**
693
+ * Dispatches an event to all registered listeners
694
+ * Listeners are resolved from the DI container and their `onEvent` method is called
695
+ *
696
+ * @param event - The event instance to dispatch
697
+ *
698
+ * @example
699
+ * ```typescript
700
+ * provider.dispatch(new UserCreatedEvent(user))
701
+ * ```
702
+ */
703
+ dispatch(event: object): void;
704
+ /**
705
+ * Checks if any listeners are registered for an event type
706
+ *
707
+ * @param eventToken - The event class/constructor to check
708
+ * @returns `true` if at least one listener is registered
709
+ */
710
+ hasListeners(eventToken: EventToken): boolean;
711
+ /**
712
+ * Removes all listeners for a specific event type
713
+ *
714
+ * @param eventToken - The event class/constructor to clear
715
+ */
716
+ clearListeners(eventToken: EventToken): void;
717
+ /**
718
+ * Removes all registered listeners from all events
719
+ */
720
+ clearAllListeners(): void;
721
+ /**
722
+ * Returns the underlying event dispatcher implementation
723
+ * Useful for advanced use cases or testing
724
+ *
725
+ * @returns The internal data structure (implementation-specific)
726
+ */
727
+ getUnderlyingDispatcher(): unknown;
728
+ }
729
+ /**
730
+ * Configuration options for creating an EventDispatcherProvider
731
+ */
732
+ interface EventDispatcherProviderOptions {
733
+ /**
734
+ * The DI container provider used to resolve listener instances
735
+ * Listeners are resolved from this container when events are dispatched
736
+ */
737
+ containerProvider: ContainerProvider;
738
+ }
739
+ //#endregion
740
+ //#region src/EventDispatcher/Provider/MutableEventDispatcherProvider.d.ts
741
+ /**
742
+ * Default EventDispatcherProvider implementation
743
+ *
744
+ * This provider stores listeners in memory and resolves them through the DI container
745
+ * when dispatching events. Each listener must implement an `onEvent(event)` method.
746
+ *
747
+ * @example Basic usage
748
+ * ```typescript
749
+ * import {
750
+ * MutableEventDispatcherProvider,
751
+ * useEventDispatcherProvider,
752
+ * getContainerProvider
753
+ * } from '@djodjonx/wiredi'
754
+ *
755
+ * const eventProvider = new MutableEventDispatcherProvider({
756
+ * containerProvider: getContainerProvider()
757
+ * })
758
+ * useEventDispatcherProvider(eventProvider)
759
+ * ```
760
+ *
761
+ * @example Dispatching events
762
+ * ```typescript
763
+ * const dispatcher = getEventDispatcherProvider()
764
+ * dispatcher.dispatch(new UserCreatedEvent(user))
765
+ * ```
766
+ */
767
+ declare class MutableEventDispatcherProvider implements EventDispatcherProvider {
768
+ /** @inheritdoc */
769
+ readonly name = "mutable-event-dispatcher";
770
+ /** Map of event names to their registered listener tokens */
771
+ private listeners;
772
+ /** DI container provider for resolving listener instances */
773
+ private containerProvider;
774
+ /**
775
+ * Creates a new MutableEventDispatcherProvider instance
776
+ *
777
+ * @param options - Configuration options including the container provider
778
+ */
779
+ constructor(options: EventDispatcherProviderOptions);
780
+ /**
781
+ * Extracts the event name from an event token (class constructor)
782
+ * @internal
783
+ */
784
+ private getEventName;
785
+ /**
786
+ * Extracts the event name from an event instance
787
+ * @internal
788
+ */
789
+ private getEventNameFromInstance;
790
+ /** @inheritdoc */
791
+ register(eventToken: EventToken, listenerToken: ListenerToken): void;
792
+ /** @inheritdoc */
793
+ dispatch(event: object): void;
794
+ /** @inheritdoc */
795
+ hasListeners(eventToken: EventToken): boolean;
796
+ /** @inheritdoc */
797
+ clearListeners(eventToken: EventToken): void;
798
+ /** @inheritdoc */
799
+ clearAllListeners(): void;
800
+ /**
801
+ * Returns the internal listeners map
802
+ * @returns Map of event names to listener tokens
803
+ */
804
+ getUnderlyingDispatcher(): Map<string, ListenerToken[]>;
805
+ }
806
+ //#endregion
807
+ //#region src/EventDispatcher/Provider/index.d.ts
808
+ /**
809
+ * Sets the global EventDispatcherProvider instance
810
+ *
811
+ * Call this once at application startup after setting up the container provider.
812
+ * The event dispatcher uses the container provider to resolve listener instances.
813
+ *
814
+ * @param provider - The EventDispatcherProvider implementation to use
815
+ * @throws Error if a provider is already registered
816
+ *
817
+ * @example
818
+ * ```typescript
819
+ * import {
820
+ * useContainerProvider,
821
+ * TsyringeProvider,
822
+ * useEventDispatcherProvider,
823
+ * MutableEventDispatcherProvider,
824
+ * getContainerProvider
825
+ * } from '@djodjonx/wiredi'
826
+ *
827
+ * // 1. Setup DI container first
828
+ * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))
829
+ *
830
+ * // 2. Setup event dispatcher (optional)
831
+ * useEventDispatcherProvider(new MutableEventDispatcherProvider({
832
+ * containerProvider: getContainerProvider()
833
+ * }))
834
+ * ```
835
+ */
836
+ declare function useEventDispatcherProvider(provider: EventDispatcherProvider): void;
837
+ /**
838
+ * Retrieves the currently registered EventDispatcherProvider
839
+ *
840
+ * @returns The registered EventDispatcherProvider instance
841
+ * @throws Error if no provider has been registered
842
+ *
843
+ * @example
844
+ * ```typescript
845
+ * const eventDispatcher = getEventDispatcherProvider()
846
+ * eventDispatcher.dispatch(new UserCreatedEvent(user))
847
+ * ```
848
+ */
849
+ declare function getEventDispatcherProvider(): EventDispatcherProvider;
850
+ /**
851
+ * Checks if an EventDispatcherProvider has been registered
852
+ *
853
+ * @returns `true` if a provider is registered, `false` otherwise
854
+ *
855
+ * @example
856
+ * ```typescript
857
+ * if (hasEventDispatcherProvider()) {
858
+ * getEventDispatcherProvider().dispatch(event)
859
+ * }
860
+ * ```
861
+ */
862
+ declare function hasEventDispatcherProvider(): boolean;
863
+ /**
864
+ * Resets the global EventDispatcherProvider
865
+ *
866
+ * Clears all registered listeners and removes the provider.
867
+ * Useful for testing or reconfiguration scenarios.
868
+ *
869
+ * ⚠️ WARNING: This should rarely be used in production code.
870
+ *
871
+ * @example
872
+ * ```typescript
873
+ * // In a test file
874
+ * afterEach(() => {
875
+ * resetEventDispatcherProvider()
876
+ * })
877
+ * ```
878
+ */
879
+ declare function resetEventDispatcherProvider(): void;
880
+ //#endregion
881
+ //#region src/index.d.ts
882
+ type Constructor<T = any> = new (...args: any[]) => T;
883
+ interface BuilderConfigEntryValue<C = null> {
884
+ token: symbol;
885
+ value: <R>(context?: C) => R;
886
+ }
887
+ interface BuilderConfigEntryInjectionWithToken {
888
+ token: symbol;
889
+ provider: Constructor;
890
+ lifecycle?: ProviderLifecycle;
891
+ }
892
+ interface BuilderConfigEntryInjectionWithClass {
893
+ token: Constructor;
894
+ lifecycle?: ProviderLifecycle;
895
+ }
896
+ interface BuilderConfigEntryFactory {
897
+ token: symbol;
898
+ factory: (provider: ContainerProvider) => any;
899
+ }
900
+ type BuilderConfigEntries<C> = BuilderConfigEntryValue<C> | BuilderConfigEntryInjectionWithToken | BuilderConfigEntryFactory | BuilderConfigEntryInjectionWithClass;
901
+ type InjectionConfig<C> = readonly BuilderConfigEntries<C>[];
902
+ interface EventEntry {
903
+ event: Constructor;
904
+ listener: Constructor;
905
+ }
906
+ type EventConfig = readonly EventEntry[];
907
+ interface BuilderConfig<C = null> {
908
+ builderId: string;
909
+ injections: InjectionConfig<C>;
910
+ listeners: EventConfig;
911
+ }
912
+ /**
913
+ * A partial builder configuration that defines a set of injections and listeners.
914
+ * Partials are "traits" or "mixins" that can be composed into a main `BuilderConfig`.
915
+ *
916
+ * NOTE: Partials cannot extend other partials to prevent hidden dependency chains.
917
+ */
918
+ interface PartialBuilderConfig<C = null> {
919
+ injections?: InjectionConfig<C>;
920
+ listeners?: EventConfig;
921
+ }
922
+ type ResolveToken<T> = symbol | Constructor<T>;
923
+ /**
924
+ * Helper type to extract the tuple of tokens from the injections config.
925
+ */
926
+ type ExtractTokens<T> = { [K in keyof T]: T[K] extends {
927
+ token: infer Token;
928
+ } ? Token : never };
929
+ /**
930
+ * A builder configuration with strictly inferred token types.
931
+ * @template C The context type.
932
+ * @template Tokens The tuple of allowed tokens.
933
+ */
934
+ interface TypedBuilderConfig<C, Tokens> extends BuilderConfig<C> {
935
+ readonly __tokens?: Tokens;
936
+ }
937
+ /**
938
+ * A partial builder configuration with strictly inferred token types.
939
+ * @template C The context type.
940
+ * @template Tokens The tuple of allowed tokens.
941
+ */
942
+ interface TypedPartialConfig<C, Tokens> extends PartialBuilderConfig<C> {
943
+ readonly __tokens?: Tokens;
944
+ }
945
+ /**
946
+ * Interface for the return object of `useBuilder`, providing a `resolve` method.
947
+ * The `AllowedTokens` generic parameter strictly types which tokens can be resolved.
948
+ */
949
+ interface IUseBuilder<AllowedTokens = ResolveToken<any>> {
950
+ /**
951
+ * Resolves a class dependency.
952
+ * The return type is automatically inferred as the class instance.
953
+ *
954
+ * @template Token The class constructor type (inferred from argument).
955
+ * @param token The class constructor token.
956
+ * @returns The instance of the class.
957
+ */
958
+ resolve<Token extends Extract<AllowedTokens, Constructor<any>>>(token: Token): InstanceType<Token>;
959
+ /**
960
+ * Resolves a dependency from the container (for Symbols or explicit types).
961
+ *
962
+ * @template T The type of the dependency to resolve.
963
+ * @param token The token (symbol or constructor) of the dependency.
964
+ * This is strictly type-checked against the `injections` defined in the builder config.
965
+ * @returns The resolved instance of the dependency.
966
+ */
967
+ resolve<T>(token: AllowedTokens & ResolveToken<T>): T;
968
+ }
969
+ /**
970
+ * Helper to define a partial configuration (injections/listeners).
971
+ *
972
+ * Partials are designed to be flat collections of dependencies. They do not support
973
+ * inheritance (`extends`) or overriding to prevent complex dependency graphs.
974
+ * All conflict resolution must happen in the main `defineBuilderConfig`.
975
+ *
976
+ * @template C The type of the context object (optional).
977
+ * @template I The specific type of the injections array (inferred).
978
+ * @param config The partial builder configuration object.
979
+ * @returns The configuration object typed as TypedPartialConfig.
980
+ */
981
+ declare function definePartialConfig<C = null, const I extends InjectionConfig<C> = InjectionConfig<C>>(config: PartialBuilderConfig<C> & {
982
+ injections?: I;
983
+ }): TypedPartialConfig<C, ExtractTokens<I>>;
984
+ /**
985
+ * Recursively extracts tokens from a tuple of TypedPartialConfigs.
986
+ */
987
+ type ExtractTokensFromTypedPartials<T extends readonly TypedPartialConfig<any, any>[]> = T extends readonly [infer Head, ...infer Tail] ? Tail extends readonly TypedPartialConfig<any, any>[] ? Head extends TypedPartialConfig<any, infer Tokens> ? Tokens extends readonly any[] ? [...Tokens, ...ExtractTokensFromTypedPartials<Tail>] : ExtractTokensFromTypedPartials<Tail> : ExtractTokensFromTypedPartials<Tail> : [] : [];
988
+ /**
989
+ * Helper to extract (Event, Listener) pairs from partials for duplicate checking.
990
+ */
991
+ type ExtractListenersFromPartials<T extends readonly TypedPartialConfig<any, any>[]> = T extends readonly [infer Head, ...infer Tail] ? Tail extends readonly TypedPartialConfig<any, any>[] ? Head extends {
992
+ listeners?: readonly (infer L)[];
993
+ } ? L | ExtractListenersFromPartials<Tail> : ExtractListenersFromPartials<Tail> : never : never;
994
+ /**
995
+ * Validates that injections do not collide with tokens from inherited partials.
996
+ *
997
+ * Rules:
998
+ * 1. Token exists in Partial -> ❌ Error: Token collision (duplicates not allowed)
999
+ * 2. Token NOT in Partial -> ✅ Valid New Entry
1000
+ *
1001
+ * Note: Token overrides are not allowed. Each token must be unique across all partials
1002
+ * and the main configuration. This prevents accidental redefinition of dependencies.
1003
+ */
1004
+ type ValidateInjections<LocalInjections, InheritedTokenUnion> = [InheritedTokenUnion] extends [never] ? LocalInjections : { [K in keyof LocalInjections]: LocalInjections[K] extends {
1005
+ token: infer T;
1006
+ } ? T extends InheritedTokenUnion ? {
1007
+ error: '[WireDI] This token is already registered in a partial. Remove it from here or from the partial to avoid conflicts.';
1008
+ token: T;
1009
+ hint: 'Each token can only be registered once across all partials and the main config.';
1010
+ } : LocalInjections[K] : LocalInjections[K] };
1011
+ /**
1012
+ * Validates that local listeners do not duplicate listeners already defined in partials.
1013
+ * Duplicate = Same Event class AND Same Listener class.
1014
+ */
1015
+ type ValidateListeners<LocalListeners, InheritedListenerUnion> = [InheritedListenerUnion] extends [never] ? LocalListeners : { [K in keyof LocalListeners]: LocalListeners[K] extends {
1016
+ event: infer E;
1017
+ listener: infer L;
1018
+ } ? {
1019
+ event: E;
1020
+ listener: L;
1021
+ } extends InheritedListenerUnion ? {
1022
+ error: '[WireDI] This event listener is already registered in a partial';
1023
+ event: E;
1024
+ listener: L;
1025
+ hint: 'Each (event, listener) pair can only be registered once.';
1026
+ } : LocalListeners[K] : LocalListeners[K] };
1027
+ /**
1028
+ * A helper function to define a builder configuration with strict type inference and inheritance.
1029
+ * Use this instead of manually casting with `satisfies BuilderConfig` or `as const`
1030
+ * to ensure that `useBuilder` can correctly infer the available tokens.
1031
+ *
1032
+ * This function now supports `extends` to inherit from `definePartialConfig` definitions.
1033
+ * Token collisions are strictly forbidden - each token must be unique across all partials
1034
+ * and the main configuration to prevent accidental redefinition.
1035
+ *
1036
+ * @template C The type of the context object (optional).
1037
+ * @template Partials The tuple of partial configs to extend.
1038
+ * @template LocalInjections The specific type of the local injections array (inferred).
1039
+ * @param config The builder configuration object.
1040
+ * @returns The configuration object typed as TypedBuilderConfig to simplify IDE display.
1041
+ *
1042
+ * @example
1043
+ * ```typescript
1044
+ * import { Lifecycle } from 'tsyringe';
1045
+ *
1046
+ * class MyService {}
1047
+ * class MyProvider {}
1048
+ * class MyEvent {}
1049
+ * class MyEventListener {
1050
+ * onEvent(event: MyEvent) {
1051
+ * console.log('Event received:', event);
1052
+ * }
1053
+ * }
1054
+ *
1055
+ * const MY_TOKEN = Symbol('MY_TOKEN');
1056
+ * const MY_VALUE_TOKEN = Symbol('MY_VALUE_TOKEN');
1057
+ * const MY_FACTORY_TOKEN = Symbol('MY_FACTORY_TOKEN');
1058
+ *
1059
+ * // --- Partial Configuration ---
1060
+ * const myPartial = definePartialConfig({
1061
+ * injections: [
1062
+ * { token: MyService } // Provides MyService
1063
+ * ],
1064
+ * listeners: [
1065
+ * { event: MyEvent, listener: MyEventListener }
1066
+ * ]
1067
+ * });
1068
+ *
1069
+ * // --- Main Builder Configuration ---
1070
+ * const myBuilderConfig = defineBuilderConfig({
1071
+ * builderId: 'my.unique.builder',
1072
+ * extends: [myPartial],
1073
+ * injections: [
1074
+ * // ❌ ERROR: Token collision - MyService is already defined in myPartial
1075
+ * // { token: MyService },
1076
+ *
1077
+ * // ✅ OK: New tokens not in partials
1078
+ * { token: MY_TOKEN, provider: MyProvider },
1079
+ * { token: MY_TOKEN, provider: MyProvider, lifecycle: Lifecycle.Transient },
1080
+ *
1081
+ * // 3. Value Injection (can use optional context)
1082
+ * { token: MY_VALUE_TOKEN, value: (context) => context?.someConfig ?? 'defaultValue' },
1083
+ *
1084
+ * // 4. Factory Injection
1085
+ * { token: MY_FACTORY_TOKEN, factory: (container) => new MyService() },
1086
+ * ],
1087
+ * listeners: [
1088
+ * // ❌ ERROR: Duplicate listener (Event + Listener pair already in myPartial)
1089
+ * // { event: MyEvent, listener: MyEventListener },
1090
+ *
1091
+ * // ✅ OK: New listener not in partials
1092
+ * { event: OtherEvent, listener: OtherEventListener },
1093
+ * ],
1094
+ * });
1095
+ *
1096
+ * // Usage:
1097
+ * // const { resolve } = useBuilder(myBuilderConfig, { someConfig: 'custom' });
1098
+ * // const service = resolve(MyService);
1099
+ * // const value = resolve(MY_VALUE_TOKEN);
1100
+ * ```
1101
+ */
1102
+ declare function defineBuilderConfig<C = null, const Partials extends readonly TypedPartialConfig<C, any>[] = [], const LocalInjections extends InjectionConfig<C> = InjectionConfig<C>, const LocalListeners extends EventConfig = EventConfig>(config: {
1103
+ builderId: string;
1104
+ extends?: Partials;
1105
+ injections: ValidateInjections<LocalInjections, ExtractTokensFromTypedPartials<Partials>[number]>;
1106
+ listeners: ValidateListeners<LocalListeners, ExtractListenersFromPartials<Partials>>;
1107
+ }): TypedBuilderConfig<C, [...ExtractTokensFromTypedPartials<Partials>, ...ExtractTokens<LocalInjections>]>;
1108
+ /**
1109
+ * A composable function for setting up and interacting with a dependency injection container
1110
+ * based on a `BuilderConfig`. It ensures that dependencies are registered only once per builderId
1111
+ * and provides a type-safe `resolve` method.
1112
+ *
1113
+ * The `resolve` method is strictly type-checked to only allow tokens defined within the `injections`
1114
+ * array of the provided `config`.
1115
+ *
1116
+ * ⚠️ Requires `useContainerProvider()` to be called first at app entry point.
1117
+ *
1118
+ * @template C The type of the context object that might be passed to value providers.
1119
+ * @template Tokens The inferred tuple of allowed tokens from the config.
1120
+ * @param config The typed builder configuration object.
1121
+ * @param context An optional context object that can be passed to value providers in the injections.
1122
+ * @returns An `IUseBuilder` instance with a type-safe `resolve` method.
1123
+ *
1124
+ * @example
1125
+ * ```typescript
1126
+ * // main.ts - Entry point
1127
+ * import { useContainerProvider, TsyringeProvider } from '@djodjonx/wiredi'
1128
+ * useContainerProvider(new TsyringeProvider())
1129
+ *
1130
+ * // anywhere.ts
1131
+ * import { useBuilder } from '@djodjonx/wiredi'
1132
+ * const { resolve } = useBuilder(myConfig)
1133
+ * const service = resolve(MyService)
1134
+ * ```
1135
+ */
1136
+ declare function useBuilder<C = null, Tokens extends readonly any[] = []>(config: TypedBuilderConfig<C, Tokens>, context?: C): IUseBuilder<Tokens[number]>;
1137
+ //#endregion
1138
+ export { AwilixProvider, type AwilixProviderOptions, BuilderConfig, type ContainerProvider, EventConfig, type EventDispatcherProvider, type EventDispatcherProviderOptions, type EventListenerEntry, type EventToken, InjectionConfig, InversifyProvider, type InversifyProviderOptions, type ListenerToken, MutableEventDispatcherProvider, PartialBuilderConfig, type ProviderAdapterOptions, ProviderLifecycle, type ProviderToken, type TsyringeDependencies, type TsyringeDependencyContainer, type TsyringeLifecycle, TsyringeProvider, type TsyringeProviderOptions, TypedBuilderConfig, TypedPartialConfig, useBuilder as default, defineBuilderConfig, definePartialConfig, getContainerProvider, getEventDispatcherProvider, hasContainerProvider, hasEventDispatcherProvider, resetContainerProvider, resetEventDispatcherProvider, useContainerProvider, useEventDispatcherProvider };
1139
+ //# sourceMappingURL=index.d.mts.map