@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.
- package/LICENSE +22 -0
- package/README.md +516 -0
- package/dist/index.cjs +931 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1139 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +1139 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +915 -0
- package/dist/index.mjs.map +1 -0
- package/dist/plugin/ConfigurationAnalyzer.d.ts +59 -0
- package/dist/plugin/ConfigurationAnalyzer.d.ts.map +1 -0
- package/dist/plugin/ConfigurationAnalyzer.js +321 -0
- package/dist/plugin/ConfigurationAnalyzer.js.map +1 -0
- package/dist/plugin/DependencyAnalyzer.d.ts +54 -0
- package/dist/plugin/DependencyAnalyzer.d.ts.map +1 -0
- package/dist/plugin/DependencyAnalyzer.js +208 -0
- package/dist/plugin/DependencyAnalyzer.js.map +1 -0
- package/dist/plugin/TokenNormalizer.d.ts +51 -0
- package/dist/plugin/TokenNormalizer.d.ts.map +1 -0
- package/dist/plugin/TokenNormalizer.js +208 -0
- package/dist/plugin/TokenNormalizer.js.map +1 -0
- package/dist/plugin/ValidationEngine.d.ts +53 -0
- package/dist/plugin/ValidationEngine.d.ts.map +1 -0
- package/dist/plugin/ValidationEngine.js +250 -0
- package/dist/plugin/ValidationEngine.js.map +1 -0
- package/dist/plugin/index.d.ts +2 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/index.js +144 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/package.json +6 -0
- package/dist/plugin/types.d.ts +152 -0
- package/dist/plugin/types.d.ts.map +1 -0
- package/dist/plugin/types.js +3 -0
- package/dist/plugin/types.js.map +1 -0
- package/package.json +95 -0
- package/plugin.js +1 -0
package/dist/index.d.mts
ADDED
|
@@ -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
|