@djodjonx/wiredi 0.0.12 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +1 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -33
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +93 -33
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -230,7 +230,7 @@ export const appConfig = defineBuilderConfig({
|
|
|
230
230
|
|
|
231
231
|
```typescript
|
|
232
232
|
// anywhere.ts
|
|
233
|
-
import useBuilder from '@djodjonx/wiredi'
|
|
233
|
+
import { useBuilder } from '@djodjonx/wiredi'
|
|
234
234
|
import { appConfig } from './config'
|
|
235
235
|
|
|
236
236
|
const { resolve } = useBuilder(appConfig)
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
1
|
let awilix = require("awilix");
|
|
3
2
|
|
|
4
3
|
//#region src/Provider/types.ts
|
|
@@ -925,7 +924,6 @@ exports.InversifyProvider = InversifyProvider;
|
|
|
925
924
|
exports.MutableEventDispatcherProvider = MutableEventDispatcherProvider;
|
|
926
925
|
exports.ProviderLifecycle = ProviderLifecycle;
|
|
927
926
|
exports.TsyringeProvider = TsyringeProvider;
|
|
928
|
-
exports.default = useBuilder;
|
|
929
927
|
exports.defineBuilderConfig = defineBuilderConfig;
|
|
930
928
|
exports.definePartialConfig = definePartialConfig;
|
|
931
929
|
exports.getContainerProvider = getContainerProvider;
|
|
@@ -934,6 +932,7 @@ exports.hasContainerProvider = hasContainerProvider;
|
|
|
934
932
|
exports.hasEventDispatcherProvider = hasEventDispatcherProvider;
|
|
935
933
|
exports.resetContainerProvider = resetContainerProvider;
|
|
936
934
|
exports.resetEventDispatcherProvider = resetEventDispatcherProvider;
|
|
935
|
+
exports.useBuilder = useBuilder;
|
|
937
936
|
exports.useContainerProvider = useContainerProvider;
|
|
938
937
|
exports.useEventDispatcherProvider = useEventDispatcherProvider;
|
|
939
938
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["awilix","Lifecycle","Lifetime","Lifecycle"],"sources":["../src/Provider/types.ts","../src/Provider/ProviderManager.ts","../src/Provider/adapters/TsyringeProvider.ts","../src/Provider/adapters/AwilixProvider.ts","../src/Provider/adapters/InversifyProvider.ts","../src/EventDispatcher/Provider/MutableEventDispatcherProvider.ts","../src/EventDispatcher/Provider/index.ts","../src/index.ts"],"sourcesContent":["/**\n * Generic constructor type\n * @template T - The type of the class instance\n */\nexport type Constructor<T = unknown> = new (...args: unknown[]) => T\n\n/**\n * Dependency lifecycle options\n * Independent of the underlying container implementation\n */\nexport enum ProviderLifecycle {\n /** Single shared instance throughout the application (default) */\n Singleton = 'singleton',\n /** New instance created on each resolution */\n Transient = 'transient',\n /** One instance per scope/child container */\n Scoped = 'scoped',\n}\n\n/**\n * Resolution token type (symbol or class constructor)\n * @template T - The type of the resolved dependency\n */\nexport type ProviderToken<T = any> = symbol | Constructor<T>\n\n/**\n * DI Container Provider Interface\n *\n * Contract that each adapter (tsyringe, awilix, inversify, etc.)\n * must implement to be compatible with WireDI.\n *\n * @example\n * ```typescript\n * class MyCustomProvider implements ContainerProvider {\n * readonly name = 'my-provider'\n * // ... implement all methods\n * }\n * ```\n */\nexport interface ContainerProvider {\n /**\n * Provider name for debugging and logging purposes\n */\n readonly name: string\n\n /**\n * Registers a static value in the container\n *\n * @template T - The type of the value\n * @param token - Symbol token to register the value under\n * @param value - The value to register\n *\n * @example\n * ```typescript\n * provider.registerValue(TOKENS.ApiUrl, 'https://api.example.com')\n * ```\n */\n registerValue<T>(token: symbol, value: T): void\n\n /**\n * Registers a factory function in the container\n *\n * @template T - The type of the value produced by the factory\n * @param token - Symbol token to register the factory under\n * @param factory - Function that creates the instance (receives the provider to resolve dependencies)\n *\n * @example\n * ```typescript\n * provider.registerFactory(TOKENS.HttpClient, (p) => {\n * return new HttpClient(p.resolve(TOKENS.ApiUrl))\n * })\n * ```\n */\n registerFactory<T>(token: symbol, factory: (provider: ContainerProvider) => T): void\n\n /**\n * Registers a class in the container\n *\n * @template T - The type of the class instance\n * @param token - Token (symbol or class) to register under\n * @param implementation - Class to instantiate (optional if token is a class)\n * @param lifecycle - Instance lifecycle (Singleton, Transient, or Scoped)\n *\n * @example\n * ```typescript\n * // Register class as its own token\n * provider.registerClass(UserService)\n *\n * // Register implementation for a symbol token\n * provider.registerClass(TOKENS.Logger, ConsoleLogger, ProviderLifecycle.Singleton)\n * ```\n */\n registerClass<T>(\n token: ProviderToken<T>,\n implementation?: Constructor<T>,\n lifecycle?: ProviderLifecycle,\n ): void\n\n /**\n * Checks if a token is already registered in the container\n *\n * @param token - Token to check\n * @returns `true` if the token is registered, `false` otherwise\n *\n * @example\n * ```typescript\n * if (!provider.isRegistered(TOKENS.Logger)) {\n * provider.registerClass(TOKENS.Logger, ConsoleLogger)\n * }\n * ```\n */\n isRegistered(token: ProviderToken): boolean\n\n /**\n * Resolves a dependency from the container\n *\n * @template T - The type of the resolved dependency\n * @param token - Token of the dependency to resolve\n * @returns Instance of the dependency\n * @throws Error if the token is not registered\n *\n * @example\n * ```typescript\n * const logger = provider.resolve<LoggerInterface>(TOKENS.Logger)\n * const userService = provider.resolve(UserService)\n * ```\n */\n resolve<T>(token: ProviderToken<T>): T\n\n /**\n * Creates a child scope (child container)\n * Useful for HTTP requests, transactions, or isolated contexts\n *\n * @returns New scoped provider instance\n *\n * @example\n * ```typescript\n * const requestScope = provider.createScope()\n * requestScope.registerValue(TOKENS.RequestId, generateRequestId())\n * ```\n */\n createScope(): ContainerProvider\n\n /**\n * Releases provider resources\n * Called during application cleanup or shutdown\n */\n dispose(): void\n\n /**\n * Access to the underlying container (for advanced use cases)\n * Return type is generic as it depends on the implementation\n *\n * @returns The underlying DI container instance\n *\n * @example\n * ```typescript\n * const tsyringeContainer = provider.getUnderlyingContainer() as DependencyContainer\n * ```\n */\n getUnderlyingContainer(): unknown\n}\n\n/**\n * Options for provider adapters\n */\nexport interface ProviderAdapterOptions {\n /**\n * Existing container to use (optional)\n * If not provided, a new container will be created\n */\n container?: unknown\n}\n\n","/**\n * Global Provider Manager for WireDI\n *\n * Manages the global DI container provider instance.\n * The provider should be configured once at application startup\n * before any calls to `useBuilder`.\n *\n * @module\n */\n\nimport type { ContainerProvider } from './types'\n\n/**\n * Currently configured global provider\n * @internal\n */\nlet currentProvider: ContainerProvider | null = null\n\n/**\n * Configures the DI container provider to use globally\n *\n * Must be called ONCE at the application entry point,\n * before any calls to `useBuilder`.\n *\n * @param provider - The provider instance to use\n * @throws Error if a provider is already configured\n *\n * @example\n * ```typescript\n * // main.ts - Application entry point\n * import 'reflect-metadata'\n * import { container, Lifecycle } from 'tsyringe'\n * import { useContainerProvider, TsyringeProvider } from '@djodjonx/wiredi'\n *\n * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))\n *\n * // Now useBuilder can be used anywhere\n * ```\n */\nexport function useContainerProvider(provider: ContainerProvider): void {\n if (currentProvider !== null) {\n throw new Error(\n `[WireDI] Provider already configured (${currentProvider.name}). ` +\n `useContainerProvider() should only be called once at app entry point. ` +\n `Use resetContainerProvider() first if you need to reconfigure.`\n )\n }\n currentProvider = provider\n}\n\n/**\n * Retrieves the configured container provider\n *\n * @returns The configured provider instance\n * @throws Error if no provider is configured\n *\n * @example\n * ```typescript\n * const provider = getContainerProvider()\n * const service = provider.resolve(MyService)\n * ```\n */\nexport function getContainerProvider(): ContainerProvider {\n if (currentProvider === null) {\n throw new Error(\n '[WireDI] No container provider configured. ' +\n 'Call useContainerProvider(provider) at your app entry point before using useBuilder. ' +\n 'Example: useContainerProvider(new TsyringeProvider({ container, Lifecycle }))'\n )\n }\n return currentProvider\n}\n\n/**\n * Checks if a provider is currently configured\n *\n * @returns `true` if a provider is configured, `false` otherwise\n *\n * @example\n * ```typescript\n * if (!hasContainerProvider()) {\n * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))\n * }\n * ```\n */\nexport function hasContainerProvider(): boolean {\n return currentProvider !== null\n}\n\n/**\n * Resets the global provider (primarily for testing)\n *\n * ⚠️ WARNING: Do not use in production, only for testing purposes\n *\n * @example\n * ```typescript\n * // In a test file\n * beforeEach(() => {\n * resetContainerProvider()\n * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))\n * })\n * ```\n */\nexport function resetContainerProvider(): void {\n if (currentProvider !== null) {\n try {\n currentProvider.dispose()\n } catch {\n // Ignore dispose errors during reset\n }\n }\n currentProvider = null\n}\n\n","/**\n * tsyringe Provider Adapter for WireDI\n *\n * This adapter allows using tsyringe as the DI container backend.\n * tsyringe is Microsoft's lightweight dependency injection container\n * for TypeScript/JavaScript using decorators.\n *\n * @remarks\n * The user must provide tsyringe dependencies to ensure the correct\n * version is used and to avoid bundling tsyringe as a direct dependency.\n *\n * @example Basic usage\n * ```typescript\n * import 'reflect-metadata'\n * import { container, Lifecycle } from 'tsyringe'\n * import { useContainerProvider, TsyringeProvider } from '@djodjonx/wiredi'\n *\n * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))\n * ```\n *\n * @example With child container for isolation\n * ```typescript\n * import { container, Lifecycle } from 'tsyringe'\n *\n * useContainerProvider(new TsyringeProvider(\n * { container, Lifecycle },\n * { useChildContainer: true }\n * ))\n * ```\n *\n * @see https://github.com/microsoft/tsyringe\n * @module\n */\n\nimport type { ContainerProvider, Constructor, ProviderToken } from '../types'\nimport { ProviderLifecycle } from '../types'\n\n/**\n * Minimal interface for tsyringe's DependencyContainer\n * Allows decoupling from the actual tsyringe package\n */\nexport interface TsyringeDependencyContainer {\n /**\n * Registers a dependency in the container\n */\n register<T>(\n token: symbol | Constructor<T>,\n provider: { useValue?: T; useFactory?: () => T; useClass?: Constructor<T> },\n options?: { lifecycle?: unknown },\n ): void\n\n /**\n * Checks if a token is registered\n */\n isRegistered(token: symbol | Constructor): boolean\n\n /**\n * Resolves a dependency from the container\n */\n resolve<T>(token: symbol | Constructor<T>): T\n\n /**\n * Creates a child container for scoped registrations\n */\n createChildContainer(): TsyringeDependencyContainer\n\n /**\n * Clears all singleton instances\n */\n clearInstances(): void\n}\n\n/**\n * Minimal interface for tsyringe's Lifecycle enum\n */\nexport interface TsyringeLifecycle {\n /** Single instance throughout the application */\n Singleton: unknown\n /** New instance on each resolution */\n Transient: unknown\n /** Single instance per child container */\n ContainerScoped: unknown\n /** Single instance per resolution tree */\n ResolutionScoped: unknown\n}\n\n/**\n * Dependencies required to create a TsyringeProvider\n * The user must provide these from their tsyringe installation\n */\nexport interface TsyringeDependencies {\n /**\n * The tsyringe container to use\n * @example `import { container } from 'tsyringe'`\n */\n container: TsyringeDependencyContainer\n\n /**\n * The tsyringe Lifecycle enum\n * @example `import { Lifecycle } from 'tsyringe'`\n */\n Lifecycle: TsyringeLifecycle\n}\n\n/**\n * Configuration options for TsyringeProvider\n */\nexport interface TsyringeProviderOptions {\n /**\n * Use a child container instead of the provided container\n * Useful for isolating registrations in tests or modules\n * @default false\n */\n useChildContainer?: boolean\n}\n\n/**\n * tsyringe adapter implementing the ContainerProvider interface\n *\n * Provides integration between WireDI and tsyringe,\n * allowing you to use tsyringe as your DI container while benefiting\n * from WireDI's configuration and validation features.\n */\nexport class TsyringeProvider implements ContainerProvider {\n /** @inheritdoc */\n readonly name = 'tsyringe'\n\n /** The tsyringe container instance */\n private readonly container: TsyringeDependencyContainer\n\n /** The tsyringe Lifecycle enum reference */\n private readonly Lifecycle: TsyringeLifecycle\n\n /**\n * Creates a new TsyringeProvider instance\n *\n * @param dependencies - tsyringe dependencies (container and Lifecycle)\n * @param options - Configuration options\n *\n * @example\n * ```typescript\n * import { container, Lifecycle } from 'tsyringe'\n *\n * const provider = new TsyringeProvider(\n * { container, Lifecycle },\n * { useChildContainer: true }\n * )\n * ```\n */\n constructor(\n dependencies: TsyringeDependencies,\n options: TsyringeProviderOptions = {},\n ) {\n this.Lifecycle = dependencies.Lifecycle\n this.container = options.useChildContainer\n ? dependencies.container.createChildContainer()\n : dependencies.container\n }\n\n /** @inheritdoc */\n registerValue<T>(token: symbol, value: T): void {\n this.container.register(token, { useValue: value })\n }\n\n /** @inheritdoc */\n registerFactory<T>(token: symbol, factory: (provider: ContainerProvider) => T): void {\n this.container.register(token, {\n useFactory: () => factory(this),\n })\n }\n\n /** @inheritdoc */\n registerClass<T>(\n token: ProviderToken<T>,\n implementation?: Constructor<T>,\n lifecycle: ProviderLifecycle = ProviderLifecycle.Singleton,\n ): void {\n const tsyringeLifecycle = this.mapLifecycle(lifecycle)\n\n if (this.isConstructor(token)) {\n this.container.register(\n token,\n { useClass: implementation ?? token },\n { lifecycle: tsyringeLifecycle },\n )\n } else {\n if (!implementation) {\n throw new Error(\n `[TsyringeProvider] Implementation required when registering symbol token: ${String(token)}`\n )\n }\n this.container.register(\n token,\n { useClass: implementation },\n { lifecycle: tsyringeLifecycle },\n )\n }\n }\n\n /** @inheritdoc */\n isRegistered(token: ProviderToken): boolean {\n return this.container.isRegistered(token)\n }\n\n /** @inheritdoc */\n resolve<T>(token: ProviderToken<T>): T {\n return this.container.resolve<T>(token)\n }\n\n /** @inheritdoc */\n createScope(): ContainerProvider {\n return new TsyringeProvider(\n { container: this.container.createChildContainer(), Lifecycle: this.Lifecycle },\n )\n }\n\n /** @inheritdoc */\n dispose(): void {\n try {\n this.container.clearInstances()\n } catch {\n // Ignore if clearInstances is not available\n }\n }\n\n /**\n * Returns the underlying tsyringe DependencyContainer\n * @returns The tsyringe container instance\n */\n getUnderlyingContainer(): TsyringeDependencyContainer {\n return this.container\n }\n\n /**\n * Maps WireDI lifecycle to tsyringe Lifecycle\n * @internal\n */\n private mapLifecycle(lifecycle: ProviderLifecycle): unknown {\n switch (lifecycle) {\n case ProviderLifecycle.Singleton:\n return this.Lifecycle.Singleton\n case ProviderLifecycle.Transient:\n return this.Lifecycle.Transient\n case ProviderLifecycle.Scoped:\n return this.Lifecycle.ContainerScoped\n default:\n return this.Lifecycle.Singleton\n }\n }\n\n /**\n * Type guard to check if a token is a class constructor\n * @internal\n */\n private isConstructor<T>(token: unknown): token is Constructor<T> {\n return typeof token === 'function'\n && !!(token as Constructor).prototype\n && (token as Constructor).prototype.constructor === token\n }\n}\n\n","/**\n * Awilix Provider Adapter for WireDI\n *\n * This adapter allows using Awilix as the DI container backend.\n * Awilix is a powerful dependency injection container for Node.js\n * that supports multiple injection modes.\n *\n * @remarks\n * Awilix uses string-based registration names internally. This provider\n * automatically maps symbol/class tokens to unique string names.\n *\n * @example Basic usage with lazy initialization\n * ```typescript\n * import { useContainerProvider, AwilixProvider } from '@djodjonx/wiredi'\n *\n * const provider = new AwilixProvider({ injectionMode: 'PROXY' })\n * await provider.init()\n * useContainerProvider(provider)\n * ```\n *\n * @example Synchronous initialization (recommended)\n * ```typescript\n * import * as awilix from 'awilix'\n * import { useContainerProvider, AwilixProvider } from '@djodjonx/wiredi'\n *\n * useContainerProvider(AwilixProvider.createSync(awilix, {\n * injectionMode: 'PROXY'\n * }))\n * ```\n *\n * @example With existing container\n * ```typescript\n * import * as awilix from 'awilix'\n * const myContainer = awilix.createContainer()\n *\n * useContainerProvider(AwilixProvider.createSync(awilix, {\n * container: myContainer\n * }))\n * ```\n *\n * @see https://github.com/jeffijoe/awilix\n * @module\n */\n\nimport type { AwilixContainer } from 'awilix'\nimport { Lifetime } from 'awilix'\nimport type { ContainerProvider, ProviderLifecycle } from '../types'\nimport { ProviderLifecycle as Lifecycle } from '../index'\n\n/**\n * Generic constructor type for class instantiation\n * @template T - The type of the class instance\n * @internal\n */\ntype Constructor<T = unknown> = new (...args: unknown[]) => T\n\n/**\n * Configuration options for AwilixProvider\n */\nexport interface AwilixProviderOptions {\n /**\n * Existing Awilix container to use\n * If not provided, a new container will be created\n * @default undefined (creates new container)\n */\n container?: AwilixContainer\n\n /**\n * Awilix injection mode\n * - `'PROXY'`: Dependencies are injected via a proxy object (recommended)\n * - `'CLASSIC'`: Dependencies are injected via constructor parameters by name\n * @default 'PROXY'\n */\n injectionMode?: 'PROXY' | 'CLASSIC'\n}\n\n/**\n * Awilix adapter implementing the ContainerProvider interface\n *\n * Provides integration between WireDI and Awilix,\n * allowing you to use Awilix as your DI container while benefiting\n * from WireDI's configuration and validation features.\n */\nexport class AwilixProvider implements ContainerProvider {\n /** @inheritdoc */\n readonly name = 'awilix'\n\n /** The Awilix container instance */\n private container: AwilixContainer\n\n /** Maps tokens to Awilix string-based registration names */\n private tokenToName = new Map<symbol | Constructor, string>()\n\n /** Counter for generating unique token names */\n private nameCounter = 0\n\n /** Lazily loaded awilix module */\n private awilix: typeof import('awilix') | null = null\n\n /**\n * Creates a new AwilixProvider instance\n *\n * @param options - Configuration options\n *\n * @remarks\n * When using the constructor directly, you must call `init()` before use,\n * or use `createSync()` for synchronous initialization.\n */\n constructor(private options: AwilixProviderOptions = {}) {\n this.container = null as any\n }\n\n /**\n * Lazily initializes the container (async)\n * @internal\n */\n private async ensureInitialized(): Promise<void> {\n if (this.container) return\n\n this.awilix = await import('awilix')\n this.container = this.options.container ?? this.awilix.createContainer({\n injectionMode: this.options.injectionMode === 'CLASSIC'\n ? this.awilix.InjectionMode.CLASSIC\n : this.awilix.InjectionMode.PROXY,\n })\n }\n\n /**\n * Throws if container is not initialized\n * @internal\n */\n private ensureInitializedSync(): void {\n if (!this.container) {\n throw new Error(\n '[AwilixProvider] Container not initialized. ' +\n 'Call await provider.init() first, or pass a pre-created container in options.'\n )\n }\n }\n\n /**\n * Initializes the provider asynchronously\n *\n * @remarks\n * Required before using the provider if not using `createSync()`.\n *\n * @example\n * ```typescript\n * const provider = new AwilixProvider({ injectionMode: 'PROXY' })\n * await provider.init()\n * useContainerProvider(provider)\n * ```\n */\n async init(): Promise<void> {\n await this.ensureInitialized()\n }\n\n /**\n * Creates a pre-initialized provider synchronously\n *\n * @param awilix - The awilix module import\n * @param options - Configuration options\n * @returns Fully initialized AwilixProvider instance\n *\n * @remarks\n * This is the recommended way to create an AwilixProvider as it\n * avoids async initialization and ensures the provider is ready immediately.\n *\n * @example\n * ```typescript\n * import * as awilix from 'awilix'\n *\n * const provider = AwilixProvider.createSync(awilix, {\n * injectionMode: 'CLASSIC'\n * })\n * ```\n */\n static createSync(awilix: typeof import('awilix'), options: AwilixProviderOptions = {}): AwilixProvider {\n const provider = new AwilixProvider(options)\n provider.awilix = awilix\n provider.container = options.container ?? awilix.createContainer({\n injectionMode: options.injectionMode === 'CLASSIC'\n ? awilix.InjectionMode.CLASSIC\n : awilix.InjectionMode.PROXY,\n })\n return provider\n }\n\n /**\n * Gets or creates a unique string name for a token\n * Awilix uses string-based registration, so we map symbols/classes to strings\n * @internal\n */\n private getTokenName(token: symbol | Constructor): string {\n if (!this.tokenToName.has(token)) {\n const name = typeof token === 'symbol'\n ? token.description ?? `token_${this.nameCounter++}`\n : token.name\n this.tokenToName.set(token, name)\n }\n return this.tokenToName.get(token)!\n }\n\n /**\n * Maps WireDI lifecycle to Awilix Lifetime\n * @internal\n */\n private mapLifecycle(lifecycle?: ProviderLifecycle): typeof Lifetime[keyof typeof Lifetime] {\n this.ensureInitializedSync()\n\n switch (lifecycle) {\n case Lifecycle.Transient:\n return Lifetime.TRANSIENT\n case Lifecycle.Scoped:\n return Lifetime.SCOPED\n case Lifecycle.Singleton:\n default:\n return Lifetime.SINGLETON\n }\n }\n\n /** @inheritdoc */\n registerValue<T>(token: symbol, value: T): void {\n this.ensureInitializedSync()\n const { asValue } = this.awilix!\n const name = this.getTokenName(token)\n this.container.register({\n [name]: asValue(value),\n })\n }\n\n /** @inheritdoc */\n registerFactory<T>(token: symbol, factory: (provider: ContainerProvider) => T): void {\n this.ensureInitializedSync()\n const { asFunction } = this.awilix!\n const name = this.getTokenName(token)\n this.container.register({\n [name]: asFunction(() => factory(this)).singleton(),\n })\n }\n\n /** @inheritdoc */\n registerClass<T>(\n token: symbol | Constructor<T>,\n impl?: Constructor<T>,\n lifecycle?: ProviderLifecycle,\n ): void {\n this.ensureInitializedSync()\n const { asClass } = this.awilix!\n const name = this.getTokenName(token)\n const ClassToRegister = impl ?? (token as Constructor<T>)\n const lifetime = this.mapLifecycle(lifecycle)\n\n this.container.register({\n [name]: asClass(ClassToRegister).setLifetime(lifetime),\n })\n }\n\n /** @inheritdoc */\n isRegistered(token: symbol | Constructor): boolean {\n this.ensureInitializedSync()\n const name = this.getTokenName(token)\n return this.container.hasRegistration(name)\n }\n\n /** @inheritdoc */\n resolve<T>(token: symbol | Constructor<T>): T {\n this.ensureInitializedSync()\n const name = this.getTokenName(token)\n return this.container.resolve<T>(name)\n }\n\n /** @inheritdoc */\n createScope(): ContainerProvider {\n this.ensureInitializedSync()\n const scopedContainer = this.container.createScope()\n const scopedProvider = AwilixProvider.createSync(this.awilix!, {\n container: scopedContainer,\n })\n this.tokenToName.forEach((name, token) => {\n scopedProvider.tokenToName.set(token, name)\n })\n return scopedProvider\n }\n\n /** @inheritdoc */\n dispose(): void {\n if (this.container) {\n this.container.dispose()\n }\n }\n\n /**\n * Returns the underlying Awilix container instance\n * @returns The AwilixContainer instance\n */\n getUnderlyingContainer(): AwilixContainer {\n this.ensureInitializedSync()\n return this.container\n }\n}\n\n","/**\n * InversifyJS Provider Adapter for WireDI\n *\n * This adapter allows using InversifyJS as the DI container backend.\n * InversifyJS is a powerful and lightweight inversion of control container\n * for JavaScript & Node.js apps powered by TypeScript.\n *\n * @remarks\n * Classes registered with this provider must be decorated with `@injectable()`.\n * The provider supports lazy initialization or synchronous initialization via `createSync()`.\n *\n * @example Basic usage with lazy initialization\n * ```typescript\n * import { useContainerProvider, InversifyProvider } from '@djodjonx/wiredi'\n *\n * const provider = new InversifyProvider()\n * await provider.init()\n * useContainerProvider(provider)\n * ```\n *\n * @example Synchronous initialization (recommended)\n * ```typescript\n * import 'reflect-metadata'\n * import * as inversify from 'inversify'\n * import { useContainerProvider, InversifyProvider } from '@djodjonx/wiredi'\n *\n * useContainerProvider(InversifyProvider.createSync(inversify))\n * ```\n *\n * @example With existing container\n * ```typescript\n * import * as inversify from 'inversify'\n * const myContainer = new inversify.Container()\n *\n * useContainerProvider(InversifyProvider.createSync(inversify, {\n * container: myContainer\n * }))\n * ```\n *\n * @see https://github.com/inversify/InversifyJS\n * @module\n */\n\nimport type { Container } from 'inversify'\nimport type { ContainerProvider, ProviderLifecycle } from '../types'\nimport { ProviderLifecycle as Lifecycle } from '../index'\n\n/**\n * Generic constructor type for class instantiation\n * @template T - The type of the class instance\n * @internal\n */\ntype Constructor<T = unknown> = new (...args: unknown[]) => T\n\n/**\n * InversifyJS binding scope options\n * @internal\n */\ntype BindingScope = 'Singleton' | 'Transient' | 'Request'\n\n/**\n * Configuration options for InversifyProvider\n */\nexport interface InversifyProviderOptions {\n /**\n * Existing Inversify container to use\n * If not provided, a new container will be created\n * @default undefined (creates new container)\n */\n container?: Container\n\n /**\n * Default binding scope for registrations without explicit lifecycle\n * @default 'Singleton'\n */\n defaultScope?: BindingScope\n}\n\n/**\n * InversifyJS adapter implementing the ContainerProvider interface\n *\n * Provides integration between WireDI and InversifyJS,\n * allowing you to use InversifyJS as your DI container while benefiting\n * from WireDI's configuration and validation features.\n */\nexport class InversifyProvider implements ContainerProvider {\n /** @inheritdoc */\n readonly name = 'inversify'\n\n /** The InversifyJS container instance */\n private container: Container\n\n /** Default scope for bindings */\n private defaultScope: BindingScope\n\n /** Lazily loaded inversify module */\n private inversify: typeof import('inversify') | null = null\n\n /**\n * Creates a new InversifyProvider instance\n *\n * @param options - Configuration options\n *\n * @remarks\n * When using the constructor directly, you must call `init()` before use,\n * or use `createSync()` for synchronous initialization.\n */\n constructor(private options: InversifyProviderOptions = {}) {\n this.defaultScope = options.defaultScope ?? 'Singleton'\n this.container = null as any\n }\n\n /**\n * Lazily initializes the container (async)\n * @internal\n */\n private async ensureInitialized(): Promise<void> {\n if (this.container) return\n\n this.inversify = await import('inversify')\n this.container = this.options.container ?? new this.inversify.Container()\n }\n\n /**\n * Throws if container is not initialized\n * @internal\n */\n private ensureInitializedSync(): void {\n if (!this.container) {\n throw new Error(\n '[InversifyProvider] Container not initialized. ' +\n 'Call await provider.init() first, or pass a pre-created container in options.'\n )\n }\n }\n\n /**\n * Initializes the provider asynchronously\n *\n * @remarks\n * Required before using the provider if not using `createSync()`.\n *\n * @example\n * ```typescript\n * const provider = new InversifyProvider()\n * await provider.init()\n * useContainerProvider(provider)\n * ```\n */\n async init(): Promise<void> {\n await this.ensureInitialized()\n }\n\n /**\n * Creates a pre-initialized provider synchronously\n *\n * @param inversify - The inversify module import\n * @param options - Configuration options\n * @returns Fully initialized InversifyProvider instance\n *\n * @remarks\n * This is the recommended way to create an InversifyProvider as it\n * avoids async initialization and ensures the provider is ready immediately.\n *\n * @example\n * ```typescript\n * import * as inversify from 'inversify'\n *\n * const provider = InversifyProvider.createSync(inversify, {\n * defaultScope: 'Transient'\n * })\n * ```\n */\n static createSync(inversify: typeof import('inversify'), options: InversifyProviderOptions = {}): InversifyProvider {\n const provider = new InversifyProvider(options)\n provider.inversify = inversify\n provider.container = options.container ?? new inversify.Container()\n return provider\n }\n\n /**\n * Maps WireDI lifecycle to InversifyJS binding scope\n * @internal\n */\n private mapLifecycle(lifecycle?: ProviderLifecycle): BindingScope {\n switch (lifecycle) {\n case Lifecycle.Transient:\n return 'Transient'\n case Lifecycle.Scoped:\n return 'Request'\n case Lifecycle.Singleton:\n default:\n return 'Singleton'\n }\n }\n\n /**\n * Applies the scope to an InversifyJS binding\n * @internal\n */\n private applyScope(\n binding: {\n inSingletonScope(): unknown\n inTransientScope(): unknown\n inRequestScope(): unknown\n },\n scope: BindingScope,\n ): void {\n switch (scope) {\n case 'Singleton':\n binding.inSingletonScope()\n break\n case 'Transient':\n binding.inTransientScope()\n break\n case 'Request':\n binding.inRequestScope()\n break\n }\n }\n\n /** @inheritdoc */\n registerValue<T>(token: symbol, value: T): void {\n this.ensureInitializedSync()\n\n if (this.container.isBound(token)) {\n this.container.unbind(token)\n }\n this.container.bind(token).toConstantValue(value)\n }\n\n /** @inheritdoc */\n registerFactory<T>(token: symbol, factory: (provider: ContainerProvider) => T): void {\n this.ensureInitializedSync()\n\n if (this.container.isBound(token)) {\n this.container.unbind(token)\n }\n this.container.bind(token).toDynamicValue(() => factory(this))\n }\n\n /** @inheritdoc */\n registerClass<T>(\n token: symbol | Constructor<T>,\n impl?: Constructor<T>,\n lifecycle?: ProviderLifecycle,\n ): void {\n this.ensureInitializedSync()\n\n const ClassToRegister = impl ?? (token as Constructor<T>)\n const scope = this.mapLifecycle(lifecycle)\n\n if (this.container.isBound(token)) {\n this.container.unbind(token)\n }\n\n const binding = this.container.bind(token).to(ClassToRegister)\n this.applyScope(binding, scope)\n }\n\n /** @inheritdoc */\n isRegistered(token: symbol | Constructor): boolean {\n this.ensureInitializedSync()\n return this.container.isBound(token)\n }\n\n /** @inheritdoc */\n resolve<T>(token: symbol | Constructor<T>): T {\n this.ensureInitializedSync()\n return this.container.get<T>(token)\n }\n\n /** @inheritdoc */\n createScope(): ContainerProvider {\n this.ensureInitializedSync()\n const childContainer = new this.inversify!.Container()\n return InversifyProvider.createSync(this.inversify!, {\n container: childContainer,\n defaultScope: this.defaultScope,\n })\n }\n\n /** @inheritdoc */\n dispose(): void {\n if (this.container) {\n this.container.unbindAll()\n }\n }\n\n /**\n * Returns the underlying InversifyJS Container instance\n * @returns The InversifyJS Container\n */\n getUnderlyingContainer(): Container {\n this.ensureInitializedSync()\n return this.container\n }\n}\n\n","/**\n * Mutable Event Dispatcher Provider\n *\n * Default implementation of EventDispatcherProvider that stores\n * listeners in memory and resolves them through the DI container.\n *\n * @module\n */\n\nimport type {\n EventDispatcherProvider,\n EventDispatcherProviderOptions,\n EventToken,\n ListenerToken,\n} from './types'\nimport type { ContainerProvider } from '../../Provider'\n\n/**\n * Default EventDispatcherProvider implementation\n *\n * This provider stores listeners in memory and resolves them through the DI container\n * when dispatching events. Each listener must implement an `onEvent(event)` method.\n *\n * @example Basic usage\n * ```typescript\n * import {\n * MutableEventDispatcherProvider,\n * useEventDispatcherProvider,\n * getContainerProvider\n * } from '@djodjonx/wiredi'\n *\n * const eventProvider = new MutableEventDispatcherProvider({\n * containerProvider: getContainerProvider()\n * })\n * useEventDispatcherProvider(eventProvider)\n * ```\n *\n * @example Dispatching events\n * ```typescript\n * const dispatcher = getEventDispatcherProvider()\n * dispatcher.dispatch(new UserCreatedEvent(user))\n * ```\n */\nexport class MutableEventDispatcherProvider implements EventDispatcherProvider {\n /** @inheritdoc */\n readonly name = 'mutable-event-dispatcher'\n\n /** Map of event names to their registered listener tokens */\n private listeners: Map<string, ListenerToken[]> = new Map()\n\n /** DI container provider for resolving listener instances */\n private containerProvider: ContainerProvider\n\n /**\n * Creates a new MutableEventDispatcherProvider instance\n *\n * @param options - Configuration options including the container provider\n */\n constructor(options: EventDispatcherProviderOptions) {\n this.containerProvider = options.containerProvider\n }\n\n /**\n * Extracts the event name from an event token (class constructor)\n * @internal\n */\n private getEventName(eventToken: EventToken): string {\n return eventToken.name\n }\n\n /**\n * Extracts the event name from an event instance\n * @internal\n */\n private getEventNameFromInstance(event: object): string {\n return event.constructor.name\n }\n\n /** @inheritdoc */\n register(eventToken: EventToken, listenerToken: ListenerToken): void {\n const eventName = this.getEventName(eventToken)\n\n if (!this.listeners.has(eventName)) {\n this.listeners.set(eventName, [])\n }\n\n this.listeners.get(eventName)!.push(listenerToken)\n }\n\n /** @inheritdoc */\n dispatch(event: object): void {\n const eventName = this.getEventNameFromInstance(event)\n const listenerTokens = this.listeners.get(eventName) ?? []\n\n for (const listenerToken of listenerTokens) {\n try {\n // ListenerToken can be a symbol or a constructor, both are valid ProviderToken types\n const listener = this.containerProvider.resolve<{ onEvent(event: object): void }>(\n listenerToken as symbol | { new (...args: unknown[]): { onEvent(event: object): void } }\n )\n listener.onEvent(event)\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.stack || error.message : String(error)\n console.error(\n `[MutableEventDispatcherProvider] Error dispatching event \"${eventName}\":`,\n errorMessage\n )\n throw error\n }\n }\n }\n\n /** @inheritdoc */\n hasListeners(eventToken: EventToken): boolean {\n const eventName = this.getEventName(eventToken)\n const listeners = this.listeners.get(eventName)\n return listeners !== undefined && listeners.length > 0\n }\n\n /** @inheritdoc */\n hasListener(eventToken: EventToken, listenerToken: ListenerToken): boolean {\n const eventName = this.getEventName(eventToken)\n const listeners = this.listeners.get(eventName)\n if (!listeners) return false\n return listeners.includes(listenerToken)\n }\n\n /** @inheritdoc */\n clearListeners(eventToken: EventToken): void {\n const eventName = this.getEventName(eventToken)\n this.listeners.delete(eventName)\n }\n\n /** @inheritdoc */\n clearAllListeners(): void {\n this.listeners.clear()\n }\n\n /**\n * Returns the internal listeners map\n * @returns Map of event names to listener tokens\n */\n getUnderlyingDispatcher(): Map<string, ListenerToken[]> {\n return this.listeners\n }\n}\n\n","/**\n * Event Dispatcher Provider Module\n *\n * Provides global management of the event dispatcher provider.\n * The event dispatcher is optional - if not configured, event listeners\n * in builder configurations are silently ignored.\n *\n * @module\n */\n\nimport type { EventDispatcherProvider } from './types'\n\nexport type {\n EventDispatcherProvider,\n EventDispatcherProviderOptions,\n EventToken,\n ListenerToken,\n EventListenerEntry,\n} from './types'\n\nexport { MutableEventDispatcherProvider } from './MutableEventDispatcherProvider'\n\n/**\n * Currently configured global event dispatcher provider\n * @internal\n */\nlet globalEventDispatcherProvider: EventDispatcherProvider | null = null\n\n/**\n * Sets the global EventDispatcherProvider instance\n *\n * Call this once at application startup after setting up the container provider.\n * The event dispatcher uses the container provider to resolve listener instances.\n *\n * @param provider - The EventDispatcherProvider implementation to use\n * @throws Error if a provider is already registered\n *\n * @example\n * ```typescript\n * import {\n * useContainerProvider,\n * TsyringeProvider,\n * useEventDispatcherProvider,\n * MutableEventDispatcherProvider,\n * getContainerProvider\n * } from '@djodjonx/wiredi'\n *\n * // 1. Setup DI container first\n * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))\n *\n * // 2. Setup event dispatcher (optional)\n * useEventDispatcherProvider(new MutableEventDispatcherProvider({\n * containerProvider: getContainerProvider()\n * }))\n * ```\n */\nexport function useEventDispatcherProvider(provider: EventDispatcherProvider): void {\n if (globalEventDispatcherProvider !== null) {\n throw new Error(\n `[EventDispatcher] Provider already registered: \"${globalEventDispatcherProvider.name}\". ` +\n `Cannot register \"${provider.name}\". Call resetEventDispatcherProvider() first if you need to change it.`\n )\n }\n globalEventDispatcherProvider = provider\n}\n\n/**\n * Retrieves the currently registered EventDispatcherProvider\n *\n * @returns The registered EventDispatcherProvider instance\n * @throws Error if no provider has been registered\n *\n * @example\n * ```typescript\n * const eventDispatcher = getEventDispatcherProvider()\n * eventDispatcher.dispatch(new UserCreatedEvent(user))\n * ```\n */\nexport function getEventDispatcherProvider(): EventDispatcherProvider {\n if (globalEventDispatcherProvider === null) {\n throw new Error(\n '[EventDispatcher] No provider registered. ' +\n 'Call useEventDispatcherProvider() at application startup.'\n )\n }\n return globalEventDispatcherProvider\n}\n\n/**\n * Checks if an EventDispatcherProvider has been registered\n *\n * @returns `true` if a provider is registered, `false` otherwise\n *\n * @example\n * ```typescript\n * if (hasEventDispatcherProvider()) {\n * getEventDispatcherProvider().dispatch(event)\n * }\n * ```\n */\nexport function hasEventDispatcherProvider(): boolean {\n return globalEventDispatcherProvider !== null\n}\n\n/**\n * Resets the global EventDispatcherProvider\n *\n * Clears all registered listeners and removes the provider.\n * Useful for testing or reconfiguration scenarios.\n *\n * ⚠️ WARNING: This should rarely be used in production code.\n *\n * @example\n * ```typescript\n * // In a test file\n * afterEach(() => {\n * resetEventDispatcherProvider()\n * })\n * ```\n */\nexport function resetEventDispatcherProvider(): void {\n if (globalEventDispatcherProvider !== null) {\n globalEventDispatcherProvider.clearAllListeners()\n }\n globalEventDispatcherProvider = null\n}\n\n","import {\n getContainerProvider,\n type ContainerProvider,\n ProviderLifecycle,\n} from './Provider/index'\nimport {\n getEventDispatcherProvider,\n hasEventDispatcherProvider,\n} from './EventDispatcher/Provider/index'\n\n// Re-export Provider API\nexport {\n useContainerProvider,\n getContainerProvider,\n hasContainerProvider,\n resetContainerProvider,\n TsyringeProvider,\n AwilixProvider,\n InversifyProvider,\n ProviderLifecycle,\n} from './Provider/index'\n\nexport type {\n ContainerProvider,\n ProviderToken,\n ProviderAdapterOptions,\n TsyringeProviderOptions,\n TsyringeDependencies,\n TsyringeDependencyContainer,\n TsyringeLifecycle,\n AwilixProviderOptions,\n InversifyProviderOptions,\n} from './Provider/index.ts'\n\n// Re-export EventDispatcher Provider API\nexport {\n useEventDispatcherProvider,\n getEventDispatcherProvider,\n hasEventDispatcherProvider,\n resetEventDispatcherProvider,\n MutableEventDispatcherProvider,\n} from './EventDispatcher/Provider/index'\n\nexport type {\n EventDispatcherProvider,\n EventDispatcherProviderOptions,\n EventToken,\n ListenerToken,\n EventListenerEntry,\n} from './EventDispatcher/Provider/index'\n\ntype Constructor<T = unknown> = new (...args: unknown[]) => T\n\ninterface BuilderConfigEntryValue<C = null> {\n token: symbol\n value: (context?: C) => any\n}\n\ninterface BuilderConfigEntryInjectionWithToken {\n token: symbol\n provider: Constructor\n lifecycle?: ProviderLifecycle\n}\n\ninterface BuilderConfigEntryInjectionWithClass {\n token: Constructor\n lifecycle?: ProviderLifecycle\n}\n\ninterface BuilderConfigEntryFactory {\n token: symbol\n factory: (provider: ContainerProvider) => any\n}\n\ntype BuilderConfigEntries<C> = BuilderConfigEntryValue<C>\n | BuilderConfigEntryInjectionWithToken\n | BuilderConfigEntryFactory\n | BuilderConfigEntryInjectionWithClass\n\n\nexport type InjectionConfig<C> = readonly BuilderConfigEntries<C>[]\n\ninterface EventEntry {\n event: Constructor\n listener: Constructor\n}\n\n\nexport type EventConfig = readonly EventEntry[]\n\nexport interface BuilderConfig<C = null> {\n builderId: string\n injections: InjectionConfig<C>\n listeners?: EventConfig\n}\n\n/**\n * A partial builder configuration that defines a set of injections and listeners.\n * Partials are \"traits\" or \"mixins\" that can be composed into a main `BuilderConfig`.\n *\n * NOTE: Partials cannot extend other partials to prevent hidden dependency chains.\n */\nexport interface PartialBuilderConfig<C = null> {\n injections?: InjectionConfig<C>\n listeners?: EventConfig\n}\n\ntype ResolveToken<T> = symbol | Constructor<T>\n\n/**\n * Type guard to check if a token is a constructor (class).\n * @param token The token to check.\n * @returns True if the token is a constructor, false otherwise.\n */\nfunction isConstructor<T = any>(token: unknown): token is Constructor<T> {\n return typeof token === 'function'\n && !!(token as Constructor).prototype\n && (token as Constructor).prototype.constructor === token\n}\n\n/**\n * Helper type to extract the tuple of tokens from the injections config.\n */\ntype ExtractTokens<T> = {\n [K in keyof T]: T[K] extends { token: infer Token } ? Token : never\n}\n\n/**\n * A builder configuration with strictly inferred token types.\n * @template C The context type.\n * @template Tokens The tuple of allowed tokens.\n */\nexport interface TypedBuilderConfig<C, Tokens> extends BuilderConfig<C> {\n // Phantom property to carry the inferred tokens type for the IDE\n readonly __tokens?: Tokens\n}\n\n/**\n * A partial builder configuration with strictly inferred token types.\n * @template C The context type.\n * @template Tokens The tuple of allowed tokens.\n */\nexport interface TypedPartialConfig<C, Tokens> extends PartialBuilderConfig<C> {\n readonly __tokens?: Tokens\n}\n\n/**\n * Interface for the return object of `useBuilder`, providing a `resolve` method.\n * The `AllowedTokens` generic parameter strictly types which tokens can be resolved.\n */\ninterface IUseBuilder<AllowedTokens = ResolveToken<any>> {\n /**\n * Resolves a class dependency.\n * The return type is automatically inferred as the class instance.\n *\n * @template Token The class constructor type (inferred from argument).\n * @param token The class constructor token.\n * @returns The instance of the class.\n */\n resolve<Token extends Extract<AllowedTokens, Constructor<any>>>(token: Token): InstanceType<Token>\n\n /**\n * Resolves a dependency from the container (for Symbols or explicit types).\n *\n * @template T The type of the dependency to resolve.\n * @param token The token (symbol or constructor) of the dependency.\n * This is strictly type-checked against the `injections` defined in the builder config.\n * @returns The resolved instance of the dependency.\n */\n resolve<T>(token: AllowedTokens & ResolveToken<T>): T\n}\n\nfunction registerConfig<C = null>(\n provider: ContainerProvider,\n injections: InjectionConfig<C>,\n context?: C,\n): void {\n injections.forEach(entry => {\n if (provider.isRegistered(entry.token)) return\n\n if ('value' in entry) {\n // Value injection\n provider.registerValue(entry.token, entry.value(context))\n } else if ('factory' in entry) {\n // Factory injection\n provider.registerFactory(entry.token, () => entry.factory(provider))\n } else if (isConstructor(entry.token)) {\n // Class token (token is the class itself)\n const lifecycle = entry.lifecycle ?? ProviderLifecycle.Singleton\n provider.registerClass(entry.token, entry.token, lifecycle)\n } else {\n // Symbol token with provider class\n if (!('provider' in entry)) {\n throw new Error(`Provider required when registering token Symbol: ${String(entry.token)}`)\n }\n const lifecycle = entry.lifecycle ?? ProviderLifecycle.Singleton\n provider.registerClass(entry.token, entry.provider, lifecycle)\n }\n })\n}\n\n\nfunction registerEvent(\n _provider: ContainerProvider,\n listeners?: EventConfig,\n): void {\n if (!listeners || !listeners.length) return\n\n // Check if event dispatcher provider is configured\n if (!hasEventDispatcherProvider()) {\n // Silently skip if no event dispatcher is configured\n // This allows using WireDI without events\n return\n }\n\n const eventDispatcher = getEventDispatcherProvider()\n\n listeners.forEach((configEntry) => {\n if (!eventDispatcher.hasListener(configEntry.event, configEntry.listener)) {\n eventDispatcher.register(configEntry.event, configEntry.listener)\n }\n })\n}\n\n/**\n * Helper to define a partial configuration (injections/listeners).\n *\n * Partials are designed to be flat collections of dependencies. They do not support\n * inheritance (`extends`) or overriding to prevent complex dependency graphs.\n * All conflict resolution must happen in the main `defineBuilderConfig`.\n *\n * @template C The type of the context object (optional).\n * @template I The specific type of the injections array (inferred).\n * @param config The partial builder configuration object.\n * @returns The configuration object typed as TypedPartialConfig.\n */\nexport function definePartialConfig<C = null, const I extends InjectionConfig<C> = InjectionConfig<C>>(\n config: PartialBuilderConfig<C> & { injections?: I },\n): TypedPartialConfig<C, ExtractTokens<I>> {\n return config as any\n}\n\n// --- Type Helpers for `defineBuilderConfig` Extension Logic ---\n\n/**\n * Recursively extracts tokens from a tuple of TypedPartialConfigs.\n */\n// eslint-disable-next-line max-len\ntype ExtractTokensFromTypedPartials<T extends readonly TypedPartialConfig<any, any>[]> = T extends readonly [infer Head, ...infer Tail]\n ? Tail extends readonly TypedPartialConfig<any, any>[]\n ? Head extends TypedPartialConfig<any, infer Tokens>\n ? Tokens extends readonly any[]\n ? [...Tokens, ...ExtractTokensFromTypedPartials<Tail>]\n : ExtractTokensFromTypedPartials<Tail>\n : ExtractTokensFromTypedPartials<Tail>\n : []\n : []\n\n/**\n * Helper to extract (Event, Listener) pairs from partials for duplicate checking.\n */\n// eslint-disable-next-line max-len\ntype ExtractListenersFromPartials<T extends readonly TypedPartialConfig<any, any>[]> = T extends readonly [infer Head, ...infer Tail]\n ? Tail extends readonly TypedPartialConfig<any, any>[]\n ? Head extends { listeners?: readonly (infer L)[] }\n ? L | ExtractListenersFromPartials<Tail>\n : ExtractListenersFromPartials<Tail>\n : never\n : never\n\n/**\n * Validates that injections do not collide with tokens from inherited partials.\n *\n * Rules:\n * 1. Token exists in Partial -> ❌ Error: Token collision (duplicates not allowed)\n * 2. Token NOT in Partial -> ✅ Valid New Entry\n *\n * Note: Token overrides are not allowed. Each token must be unique across all partials\n * and the main configuration. This prevents accidental redefinition of dependencies.\n */\ntype ValidateInjections<LocalInjections, InheritedTokenUnion> =\n [InheritedTokenUnion] extends [never]\n // No inherited tokens, all local injections are valid (no collision possible)\n ? LocalInjections\n : {\n [K in keyof LocalInjections]: LocalInjections[K] extends { token: infer T }\n ? T extends InheritedTokenUnion\n ? {\n // eslint-disable-next-line max-len\n error: '[WireDI] This token is already registered in a partial. Remove it from here or from the partial to avoid conflicts.'\n token: T\n // eslint-disable-next-line max-len\n hint: 'Each token can only be registered once across all partials and the main config.'\n }\n : LocalInjections[K] // ✅ Valid New Entry\n : LocalInjections[K]\n }\n\n/**\n * Validates that local listeners do not duplicate listeners already defined in partials.\n * Duplicate = Same Event class AND Same Listener class.\n */\ntype ValidateListeners<LocalListeners, InheritedListenerUnion> =\n [InheritedListenerUnion] extends [never]\n // No inherited listeners, validate only internal duplicates\n ? ValidateListenersInternal<LocalListeners>\n : ValidateListenersAgainstPartials<LocalListeners, InheritedListenerUnion>\n\n/**\n * Check each local listener against inherited listeners from partials.\n * Uses strict type equality to avoid false positives.\n */\ntype ValidateListenersAgainstPartials<LocalListeners, InheritedListenerUnion> = {\n [K in keyof LocalListeners]: LocalListeners[K] extends { event: infer E, listener: infer L }\n ? IsListenerInUnion<E, L, InheritedListenerUnion> extends true\n ? {\n error: '[WireDI] This event listener is already registered in a partial'\n event: E\n listener: L\n hint: 'Each (event, listener) pair can only be registered once.'\n }\n : LocalListeners[K]\n : LocalListeners[K]\n}\n\n/**\n * Check if a specific (event, listener) pair exists in a union of listener entries.\n * Uses strict type equality for both event AND listener.\n */\ntype IsListenerInUnion<E, L, Union> = Union extends { event: infer UE, listener: infer UL }\n ? StrictEquals<E, UE> extends true\n ? StrictEquals<L, UL> extends true\n ? true\n : IsListenerInUnion<E, L, Exclude<Union, { event: UE, listener: UL }>>\n : IsListenerInUnion<E, L, Exclude<Union, { event: UE, listener: UL }>>\n : false\n\n/**\n * Strict type equality check.\n * Returns true only if A and B are exactly the same type.\n */\ntype StrictEquals<A, B> =\n (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false\n\n/**\n * Validates that there are no duplicate listeners within the same array.\n * Checks each listener against all following listeners.\n * A duplicate is defined as having BOTH the same event AND the same listener.\n */\ntype ValidateListenersInternal<T> = T extends readonly []\n ? T\n : T extends readonly [infer First, ...infer Rest]\n ? First extends { event: infer E, listener: infer L }\n ? HasExactDuplicate<E, L, Rest> extends true\n ? [\n {\n error: '[WireDI] Duplicate listener in the same configuration'\n event: E\n listener: L\n hint: 'Each (event, listener) pair must be unique within the configuration.'\n },\n ...ValidateListenersInternal<Rest>\n ]\n : [First, ...ValidateListenersInternal<Rest>]\n : [First, ...ValidateListenersInternal<Rest>]\n : T\n\n/**\n * Helper to check if an exact (event, listener) pair exists in the rest of the array.\n * Uses strict type equality to avoid false positives with structurally similar types.\n */\ntype HasExactDuplicate<E, L, Rest> = Rest extends readonly [infer First, ...infer Tail]\n ? First extends { event: infer FE, listener: infer FL }\n ? StrictEquals<E, FE> extends true\n ? StrictEquals<L, FL> extends true\n ? true\n : HasExactDuplicate<E, L, Tail>\n : HasExactDuplicate<E, L, Tail>\n : HasExactDuplicate<E, L, Tail>\n : false\n\n/**\n * A helper function to define a builder configuration with strict type inference and inheritance.\n * Use this instead of manually casting with `satisfies BuilderConfig` or `as const`\n * to ensure that `useBuilder` can correctly infer the available tokens.\n *\n * This function now supports `extends` to inherit from `definePartialConfig` definitions.\n * Token collisions are strictly forbidden - each token must be unique across all partials\n * and the main configuration to prevent accidental redefinition.\n *\n * @template C The type of the context object (optional).\n * @template Partials The tuple of partial configs to extend.\n * @template LocalInjections The specific type of the local injections array (inferred).\n * @param config The builder configuration object.\n * @returns The configuration object typed as TypedBuilderConfig to simplify IDE display.\n *\n * @example\n * ```typescript\n * import { Lifecycle } from 'tsyringe';\n *\n * class MyService {}\n * class MyProvider {}\n * class MyEvent {}\n * class MyEventListener {\n * onEvent(event: MyEvent) {\n * console.log('Event received:', event);\n * }\n * }\n *\n * const MY_TOKEN = Symbol('MY_TOKEN');\n * const MY_VALUE_TOKEN = Symbol('MY_VALUE_TOKEN');\n * const MY_FACTORY_TOKEN = Symbol('MY_FACTORY_TOKEN');\n *\n * // --- Partial Configuration ---\n * const myPartial = definePartialConfig({\n * injections: [\n * { token: MyService } // Provides MyService\n * ],\n * listeners: [\n * { event: MyEvent, listener: MyEventListener }\n * ]\n * });\n *\n * // --- Main Builder Configuration ---\n * const myBuilderConfig = defineBuilderConfig({\n * builderId: 'my.unique.builder',\n * extends: [myPartial],\n * injections: [\n * // ❌ ERROR: Token collision - MyService is already defined in myPartial\n * // { token: MyService },\n *\n * // ✅ OK: New tokens not in partials\n * { token: MY_TOKEN, provider: MyProvider },\n * { token: MY_TOKEN, provider: MyProvider, lifecycle: Lifecycle.Transient },\n *\n * // 3. Value Injection (can use optional context)\n * { token: MY_VALUE_TOKEN, value: (context) => context?.someConfig ?? 'defaultValue' },\n *\n * // 4. Factory Injection\n * { token: MY_FACTORY_TOKEN, factory: (container) => new MyService() },\n * ],\n * listeners: [\n * // ❌ ERROR: Duplicate listener (Event + Listener pair already in myPartial)\n * // { event: MyEvent, listener: MyEventListener },\n *\n * // ✅ OK: New listener not in partials\n * { event: OtherEvent, listener: OtherEventListener },\n * ],\n * });\n *\n * // Usage:\n * // const { resolve } = useBuilder(myBuilderConfig, { someConfig: 'custom' });\n * // const service = resolve(MyService);\n * // const value = resolve(MY_VALUE_TOKEN);\n * ```\n */\nexport function defineBuilderConfig<\n C = null,\n const Partials extends readonly TypedPartialConfig<C, any>[] = [],\n const LocalInjections extends InjectionConfig<C> = InjectionConfig<C>,\n const LocalListeners extends EventConfig | undefined = EventConfig | undefined,\n>(\n config: {\n builderId: string\n extends?: Partials\n injections: ValidateInjections<LocalInjections, ExtractTokensFromTypedPartials<Partials>[number]>\n listeners?: ValidateListeners<LocalListeners, ExtractListenersFromPartials<Partials>>\n },\n): TypedBuilderConfig<C, [...ExtractTokensFromTypedPartials<Partials>, ...ExtractTokens<LocalInjections>]> {\n // Runtime Logic:\n // We place local injections FIRST.\n // Since `registerConfig` checks `if (container.isRegistered(entry.token)) return`,\n // the first occurrence of a token wins. This effectively implements the override logic.\n const mergedInjections = [\n ...config.injections as InjectionConfig<C>,\n ...(config.extends || []).flatMap(p => p.injections || []),\n ]\n\n const mergedListeners = [\n ...(config.extends || []).flatMap(p => p.listeners || []),\n ...(config.listeners as EventConfig || []),\n ]\n\n return {\n ...config,\n injections: mergedInjections,\n listeners: mergedListeners,\n } as any\n}\n\n/**\n * A composable function for setting up and interacting with a dependency injection container\n * based on a `BuilderConfig`. It ensures that dependencies are registered only once per builderId\n * and provides a type-safe `resolve` method.\n *\n * The `resolve` method is strictly type-checked to only allow tokens defined within the `injections`\n * array of the provided `config`.\n *\n * ⚠️ Requires `useContainerProvider()` to be called first at app entry point.\n *\n * @template C The type of the context object that might be passed to value providers.\n * @template Tokens The inferred tuple of allowed tokens from the config.\n * @param config The typed builder configuration object.\n * @param context An optional context object that can be passed to value providers in the injections.\n * @returns An `IUseBuilder` instance with a type-safe `resolve` method.\n *\n * @example\n * ```typescript\n * // main.ts - Entry point\n * import { useContainerProvider, TsyringeProvider } from '@djodjonx/wiredi'\n * useContainerProvider(new TsyringeProvider())\n *\n * // anywhere.ts\n * import { useBuilder } from '@djodjonx/wiredi'\n * const { resolve } = useBuilder(myConfig)\n * const service = resolve(MyService)\n * ```\n */\nexport default function useBuilder<C = null, Tokens extends readonly any[] = []>(\n config: TypedBuilderConfig<C, Tokens>,\n context?: C,\n): IUseBuilder<Tokens[number]> {\n const provider = getContainerProvider()\n\n // Use builderId as a marker to ensure we only register once\n const builderIdToken = Symbol.for(`__builder__${config.builderId}`)\n\n if (!provider.isRegistered(builderIdToken)) {\n registerConfig(provider, config.injections, context)\n registerEvent(provider, config.listeners)\n provider.registerValue(builderIdToken, config.builderId)\n }\n\n const resolve = <T>(token: ResolveToken<T> & Tokens[number]): T => provider.resolve<T>(token)\n\n return {\n resolve,\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["awilix","Lifecycle","Lifetime","Lifecycle"],"sources":["../src/Provider/types.ts","../src/Provider/ProviderManager.ts","../src/Provider/adapters/TsyringeProvider.ts","../src/Provider/adapters/AwilixProvider.ts","../src/Provider/adapters/InversifyProvider.ts","../src/EventDispatcher/Provider/MutableEventDispatcherProvider.ts","../src/EventDispatcher/Provider/index.ts","../src/index.ts"],"sourcesContent":["/**\n * Generic constructor type\n * @template T - The type of the class instance\n */\nexport type Constructor<T = unknown> = new (...args: unknown[]) => T\n\n/**\n * Dependency lifecycle options\n * Independent of the underlying container implementation\n */\nexport enum ProviderLifecycle {\n /** Single shared instance throughout the application (default) */\n Singleton = 'singleton',\n /** New instance created on each resolution */\n Transient = 'transient',\n /** One instance per scope/child container */\n Scoped = 'scoped',\n}\n\n/**\n * Resolution token type (symbol or class constructor)\n * @template T - The type of the resolved dependency\n */\nexport type ProviderToken<T = any> = symbol | Constructor<T>\n\n/**\n * DI Container Provider Interface\n *\n * Contract that each adapter (tsyringe, awilix, inversify, etc.)\n * must implement to be compatible with WireDI.\n *\n * @example\n * ```typescript\n * class MyCustomProvider implements ContainerProvider {\n * readonly name = 'my-provider'\n * // ... implement all methods\n * }\n * ```\n */\nexport interface ContainerProvider {\n /**\n * Provider name for debugging and logging purposes\n */\n readonly name: string\n\n /**\n * Registers a static value in the container\n *\n * @template T - The type of the value\n * @param token - Symbol token to register the value under\n * @param value - The value to register\n *\n * @example\n * ```typescript\n * provider.registerValue(TOKENS.ApiUrl, 'https://api.example.com')\n * ```\n */\n registerValue<T>(token: symbol, value: T): void\n\n /**\n * Registers a factory function in the container\n *\n * @template T - The type of the value produced by the factory\n * @param token - Symbol token to register the factory under\n * @param factory - Function that creates the instance (receives the provider to resolve dependencies)\n *\n * @example\n * ```typescript\n * provider.registerFactory(TOKENS.HttpClient, (p) => {\n * return new HttpClient(p.resolve(TOKENS.ApiUrl))\n * })\n * ```\n */\n registerFactory<T>(token: symbol, factory: (provider: ContainerProvider) => T): void\n\n /**\n * Registers a class in the container\n *\n * @template T - The type of the class instance\n * @param token - Token (symbol or class) to register under\n * @param implementation - Class to instantiate (optional if token is a class)\n * @param lifecycle - Instance lifecycle (Singleton, Transient, or Scoped)\n *\n * @example\n * ```typescript\n * // Register class as its own token\n * provider.registerClass(UserService)\n *\n * // Register implementation for a symbol token\n * provider.registerClass(TOKENS.Logger, ConsoleLogger, ProviderLifecycle.Singleton)\n * ```\n */\n registerClass<T>(\n token: ProviderToken<T>,\n implementation?: Constructor<T>,\n lifecycle?: ProviderLifecycle,\n ): void\n\n /**\n * Checks if a token is already registered in the container\n *\n * @param token - Token to check\n * @returns `true` if the token is registered, `false` otherwise\n *\n * @example\n * ```typescript\n * if (!provider.isRegistered(TOKENS.Logger)) {\n * provider.registerClass(TOKENS.Logger, ConsoleLogger)\n * }\n * ```\n */\n isRegistered(token: ProviderToken): boolean\n\n /**\n * Resolves a dependency from the container\n *\n * @template T - The type of the resolved dependency\n * @param token - Token of the dependency to resolve\n * @returns Instance of the dependency\n * @throws Error if the token is not registered\n *\n * @example\n * ```typescript\n * const logger = provider.resolve<LoggerInterface>(TOKENS.Logger)\n * const userService = provider.resolve(UserService)\n * ```\n */\n resolve<T>(token: ProviderToken<T>): T\n\n /**\n * Creates a child scope (child container)\n * Useful for HTTP requests, transactions, or isolated contexts\n *\n * @returns New scoped provider instance\n *\n * @example\n * ```typescript\n * const requestScope = provider.createScope()\n * requestScope.registerValue(TOKENS.RequestId, generateRequestId())\n * ```\n */\n createScope(): ContainerProvider\n\n /**\n * Releases provider resources\n * Called during application cleanup or shutdown\n */\n dispose(): void\n\n /**\n * Access to the underlying container (for advanced use cases)\n * Return type is generic as it depends on the implementation\n *\n * @returns The underlying DI container instance\n *\n * @example\n * ```typescript\n * const tsyringeContainer = provider.getUnderlyingContainer() as DependencyContainer\n * ```\n */\n getUnderlyingContainer(): unknown\n}\n\n/**\n * Options for provider adapters\n */\nexport interface ProviderAdapterOptions {\n /**\n * Existing container to use (optional)\n * If not provided, a new container will be created\n */\n container?: unknown\n}\n\n","/**\n * Global Provider Manager for WireDI\n *\n * Manages the global DI container provider instance.\n * The provider should be configured once at application startup\n * before any calls to `useBuilder`.\n *\n * @module\n */\n\nimport type { ContainerProvider } from './types'\n\n/**\n * Currently configured global provider\n * @internal\n */\nlet currentProvider: ContainerProvider | null = null\n\n/**\n * Configures the DI container provider to use globally\n *\n * Must be called ONCE at the application entry point,\n * before any calls to `useBuilder`.\n *\n * @param provider - The provider instance to use\n * @throws Error if a provider is already configured\n *\n * @example\n * ```typescript\n * // main.ts - Application entry point\n * import 'reflect-metadata'\n * import { container, Lifecycle } from 'tsyringe'\n * import { useContainerProvider, TsyringeProvider } from '@djodjonx/wiredi'\n *\n * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))\n *\n * // Now useBuilder can be used anywhere\n * ```\n */\nexport function useContainerProvider(provider: ContainerProvider): void {\n if (currentProvider !== null) {\n throw new Error(\n `[WireDI] Provider already configured (${currentProvider.name}). ` +\n `useContainerProvider() should only be called once at app entry point. ` +\n `Use resetContainerProvider() first if you need to reconfigure.`\n )\n }\n currentProvider = provider\n}\n\n/**\n * Retrieves the configured container provider\n *\n * @returns The configured provider instance\n * @throws Error if no provider is configured\n *\n * @example\n * ```typescript\n * const provider = getContainerProvider()\n * const service = provider.resolve(MyService)\n * ```\n */\nexport function getContainerProvider(): ContainerProvider {\n if (currentProvider === null) {\n throw new Error(\n '[WireDI] No container provider configured. ' +\n 'Call useContainerProvider(provider) at your app entry point before using useBuilder. ' +\n 'Example: useContainerProvider(new TsyringeProvider({ container, Lifecycle }))'\n )\n }\n return currentProvider\n}\n\n/**\n * Checks if a provider is currently configured\n *\n * @returns `true` if a provider is configured, `false` otherwise\n *\n * @example\n * ```typescript\n * if (!hasContainerProvider()) {\n * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))\n * }\n * ```\n */\nexport function hasContainerProvider(): boolean {\n return currentProvider !== null\n}\n\n/**\n * Resets the global provider (primarily for testing)\n *\n * ⚠️ WARNING: Do not use in production, only for testing purposes\n *\n * @example\n * ```typescript\n * // In a test file\n * beforeEach(() => {\n * resetContainerProvider()\n * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))\n * })\n * ```\n */\nexport function resetContainerProvider(): void {\n if (currentProvider !== null) {\n try {\n currentProvider.dispose()\n } catch {\n // Ignore dispose errors during reset\n }\n }\n currentProvider = null\n}\n\n","/**\n * tsyringe Provider Adapter for WireDI\n *\n * This adapter allows using tsyringe as the DI container backend.\n * tsyringe is Microsoft's lightweight dependency injection container\n * for TypeScript/JavaScript using decorators.\n *\n * @remarks\n * The user must provide tsyringe dependencies to ensure the correct\n * version is used and to avoid bundling tsyringe as a direct dependency.\n *\n * @example Basic usage\n * ```typescript\n * import 'reflect-metadata'\n * import { container, Lifecycle } from 'tsyringe'\n * import { useContainerProvider, TsyringeProvider } from '@djodjonx/wiredi'\n *\n * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))\n * ```\n *\n * @example With child container for isolation\n * ```typescript\n * import { container, Lifecycle } from 'tsyringe'\n *\n * useContainerProvider(new TsyringeProvider(\n * { container, Lifecycle },\n * { useChildContainer: true }\n * ))\n * ```\n *\n * @see https://github.com/microsoft/tsyringe\n * @module\n */\n\nimport type { ContainerProvider, Constructor, ProviderToken } from '../types'\nimport { ProviderLifecycle } from '../types'\n\n/**\n * Minimal interface for tsyringe's DependencyContainer\n * Allows decoupling from the actual tsyringe package\n */\nexport interface TsyringeDependencyContainer {\n /**\n * Registers a dependency in the container\n */\n register<T>(\n token: symbol | Constructor<T>,\n provider: { useValue?: T; useFactory?: () => T; useClass?: Constructor<T> },\n options?: { lifecycle?: unknown },\n ): void\n\n /**\n * Checks if a token is registered\n */\n isRegistered(token: symbol | Constructor): boolean\n\n /**\n * Resolves a dependency from the container\n */\n resolve<T>(token: symbol | Constructor<T>): T\n\n /**\n * Creates a child container for scoped registrations\n */\n createChildContainer(): TsyringeDependencyContainer\n\n /**\n * Clears all singleton instances\n */\n clearInstances(): void\n}\n\n/**\n * Minimal interface for tsyringe's Lifecycle enum\n */\nexport interface TsyringeLifecycle {\n /** Single instance throughout the application */\n Singleton: unknown\n /** New instance on each resolution */\n Transient: unknown\n /** Single instance per child container */\n ContainerScoped: unknown\n /** Single instance per resolution tree */\n ResolutionScoped: unknown\n}\n\n/**\n * Dependencies required to create a TsyringeProvider\n * The user must provide these from their tsyringe installation\n */\nexport interface TsyringeDependencies {\n /**\n * The tsyringe container to use\n * @example `import { container } from 'tsyringe'`\n */\n container: TsyringeDependencyContainer\n\n /**\n * The tsyringe Lifecycle enum\n * @example `import { Lifecycle } from 'tsyringe'`\n */\n Lifecycle: TsyringeLifecycle\n}\n\n/**\n * Configuration options for TsyringeProvider\n */\nexport interface TsyringeProviderOptions {\n /**\n * Use a child container instead of the provided container\n * Useful for isolating registrations in tests or modules\n * @default false\n */\n useChildContainer?: boolean\n}\n\n/**\n * tsyringe adapter implementing the ContainerProvider interface\n *\n * Provides integration between WireDI and tsyringe,\n * allowing you to use tsyringe as your DI container while benefiting\n * from WireDI's configuration and validation features.\n */\nexport class TsyringeProvider implements ContainerProvider {\n /** @inheritdoc */\n readonly name = 'tsyringe'\n\n /** The tsyringe container instance */\n private readonly container: TsyringeDependencyContainer\n\n /** The tsyringe Lifecycle enum reference */\n private readonly Lifecycle: TsyringeLifecycle\n\n /**\n * Creates a new TsyringeProvider instance\n *\n * @param dependencies - tsyringe dependencies (container and Lifecycle)\n * @param options - Configuration options\n *\n * @example\n * ```typescript\n * import { container, Lifecycle } from 'tsyringe'\n *\n * const provider = new TsyringeProvider(\n * { container, Lifecycle },\n * { useChildContainer: true }\n * )\n * ```\n */\n constructor(\n dependencies: TsyringeDependencies,\n options: TsyringeProviderOptions = {},\n ) {\n this.Lifecycle = dependencies.Lifecycle\n this.container = options.useChildContainer\n ? dependencies.container.createChildContainer()\n : dependencies.container\n }\n\n /** @inheritdoc */\n registerValue<T>(token: symbol, value: T): void {\n this.container.register(token, { useValue: value })\n }\n\n /** @inheritdoc */\n registerFactory<T>(token: symbol, factory: (provider: ContainerProvider) => T): void {\n this.container.register(token, {\n useFactory: () => factory(this),\n })\n }\n\n /** @inheritdoc */\n registerClass<T>(\n token: ProviderToken<T>,\n implementation?: Constructor<T>,\n lifecycle: ProviderLifecycle = ProviderLifecycle.Singleton,\n ): void {\n const tsyringeLifecycle = this.mapLifecycle(lifecycle)\n\n if (this.isConstructor(token)) {\n this.container.register(\n token,\n { useClass: implementation ?? token },\n { lifecycle: tsyringeLifecycle },\n )\n } else {\n if (!implementation) {\n throw new Error(\n `[TsyringeProvider] Implementation required when registering symbol token: ${String(token)}`\n )\n }\n this.container.register(\n token,\n { useClass: implementation },\n { lifecycle: tsyringeLifecycle },\n )\n }\n }\n\n /** @inheritdoc */\n isRegistered(token: ProviderToken): boolean {\n return this.container.isRegistered(token)\n }\n\n /** @inheritdoc */\n resolve<T>(token: ProviderToken<T>): T {\n return this.container.resolve<T>(token)\n }\n\n /** @inheritdoc */\n createScope(): ContainerProvider {\n return new TsyringeProvider(\n { container: this.container.createChildContainer(), Lifecycle: this.Lifecycle },\n )\n }\n\n /** @inheritdoc */\n dispose(): void {\n try {\n this.container.clearInstances()\n } catch {\n // Ignore if clearInstances is not available\n }\n }\n\n /**\n * Returns the underlying tsyringe DependencyContainer\n * @returns The tsyringe container instance\n */\n getUnderlyingContainer(): TsyringeDependencyContainer {\n return this.container\n }\n\n /**\n * Maps WireDI lifecycle to tsyringe Lifecycle\n * @internal\n */\n private mapLifecycle(lifecycle: ProviderLifecycle): unknown {\n switch (lifecycle) {\n case ProviderLifecycle.Singleton:\n return this.Lifecycle.Singleton\n case ProviderLifecycle.Transient:\n return this.Lifecycle.Transient\n case ProviderLifecycle.Scoped:\n return this.Lifecycle.ContainerScoped\n default:\n return this.Lifecycle.Singleton\n }\n }\n\n /**\n * Type guard to check if a token is a class constructor\n * @internal\n */\n private isConstructor<T>(token: unknown): token is Constructor<T> {\n return typeof token === 'function'\n && !!(token as Constructor).prototype\n && (token as Constructor).prototype.constructor === token\n }\n}\n\n","/**\n * Awilix Provider Adapter for WireDI\n *\n * This adapter allows using Awilix as the DI container backend.\n * Awilix is a powerful dependency injection container for Node.js\n * that supports multiple injection modes.\n *\n * @remarks\n * Awilix uses string-based registration names internally. This provider\n * automatically maps symbol/class tokens to unique string names.\n *\n * @example Basic usage with lazy initialization\n * ```typescript\n * import { useContainerProvider, AwilixProvider } from '@djodjonx/wiredi'\n *\n * const provider = new AwilixProvider({ injectionMode: 'PROXY' })\n * await provider.init()\n * useContainerProvider(provider)\n * ```\n *\n * @example Synchronous initialization (recommended)\n * ```typescript\n * import * as awilix from 'awilix'\n * import { useContainerProvider, AwilixProvider } from '@djodjonx/wiredi'\n *\n * useContainerProvider(AwilixProvider.createSync(awilix, {\n * injectionMode: 'PROXY'\n * }))\n * ```\n *\n * @example With existing container\n * ```typescript\n * import * as awilix from 'awilix'\n * const myContainer = awilix.createContainer()\n *\n * useContainerProvider(AwilixProvider.createSync(awilix, {\n * container: myContainer\n * }))\n * ```\n *\n * @see https://github.com/jeffijoe/awilix\n * @module\n */\n\nimport type { AwilixContainer } from 'awilix'\nimport { Lifetime } from 'awilix'\nimport type { ContainerProvider, ProviderLifecycle } from '../types'\nimport { ProviderLifecycle as Lifecycle } from '../index'\n\n/**\n * Generic constructor type for class instantiation\n * @template T - The type of the class instance\n * @internal\n */\ntype Constructor<T = unknown> = new (...args: unknown[]) => T\n\n/**\n * Configuration options for AwilixProvider\n */\nexport interface AwilixProviderOptions {\n /**\n * Existing Awilix container to use\n * If not provided, a new container will be created\n * @default undefined (creates new container)\n */\n container?: AwilixContainer\n\n /**\n * Awilix injection mode\n * - `'PROXY'`: Dependencies are injected via a proxy object (recommended)\n * - `'CLASSIC'`: Dependencies are injected via constructor parameters by name\n * @default 'PROXY'\n */\n injectionMode?: 'PROXY' | 'CLASSIC'\n}\n\n/**\n * Awilix adapter implementing the ContainerProvider interface\n *\n * Provides integration between WireDI and Awilix,\n * allowing you to use Awilix as your DI container while benefiting\n * from WireDI's configuration and validation features.\n */\nexport class AwilixProvider implements ContainerProvider {\n /** @inheritdoc */\n readonly name = 'awilix'\n\n /** The Awilix container instance */\n private container: AwilixContainer\n\n /** Maps tokens to Awilix string-based registration names */\n private tokenToName = new Map<symbol | Constructor, string>()\n\n /** Counter for generating unique token names */\n private nameCounter = 0\n\n /** Lazily loaded awilix module */\n private awilix: typeof import('awilix') | null = null\n\n /**\n * Creates a new AwilixProvider instance\n *\n * @param options - Configuration options\n *\n * @remarks\n * When using the constructor directly, you must call `init()` before use,\n * or use `createSync()` for synchronous initialization.\n */\n constructor(private options: AwilixProviderOptions = {}) {\n this.container = null as any\n }\n\n /**\n * Lazily initializes the container (async)\n * @internal\n */\n private async ensureInitialized(): Promise<void> {\n if (this.container) return\n\n this.awilix = await import('awilix')\n this.container = this.options.container ?? this.awilix.createContainer({\n injectionMode: this.options.injectionMode === 'CLASSIC'\n ? this.awilix.InjectionMode.CLASSIC\n : this.awilix.InjectionMode.PROXY,\n })\n }\n\n /**\n * Throws if container is not initialized\n * @internal\n */\n private ensureInitializedSync(): void {\n if (!this.container) {\n throw new Error(\n '[AwilixProvider] Container not initialized. ' +\n 'Call await provider.init() first, or pass a pre-created container in options.'\n )\n }\n }\n\n /**\n * Initializes the provider asynchronously\n *\n * @remarks\n * Required before using the provider if not using `createSync()`.\n *\n * @example\n * ```typescript\n * const provider = new AwilixProvider({ injectionMode: 'PROXY' })\n * await provider.init()\n * useContainerProvider(provider)\n * ```\n */\n async init(): Promise<void> {\n await this.ensureInitialized()\n }\n\n /**\n * Creates a pre-initialized provider synchronously\n *\n * @param awilix - The awilix module import\n * @param options - Configuration options\n * @returns Fully initialized AwilixProvider instance\n *\n * @remarks\n * This is the recommended way to create an AwilixProvider as it\n * avoids async initialization and ensures the provider is ready immediately.\n *\n * @example\n * ```typescript\n * import * as awilix from 'awilix'\n *\n * const provider = AwilixProvider.createSync(awilix, {\n * injectionMode: 'CLASSIC'\n * })\n * ```\n */\n static createSync(awilix: typeof import('awilix'), options: AwilixProviderOptions = {}): AwilixProvider {\n const provider = new AwilixProvider(options)\n provider.awilix = awilix\n provider.container = options.container ?? awilix.createContainer({\n injectionMode: options.injectionMode === 'CLASSIC'\n ? awilix.InjectionMode.CLASSIC\n : awilix.InjectionMode.PROXY,\n })\n return provider\n }\n\n /**\n * Gets or creates a unique string name for a token\n * Awilix uses string-based registration, so we map symbols/classes to strings\n * @internal\n */\n private getTokenName(token: symbol | Constructor): string {\n if (!this.tokenToName.has(token)) {\n const name = typeof token === 'symbol'\n ? token.description ?? `token_${this.nameCounter++}`\n : token.name\n this.tokenToName.set(token, name)\n }\n return this.tokenToName.get(token)!\n }\n\n /**\n * Maps WireDI lifecycle to Awilix Lifetime\n * @internal\n */\n private mapLifecycle(lifecycle?: ProviderLifecycle): typeof Lifetime[keyof typeof Lifetime] {\n this.ensureInitializedSync()\n\n switch (lifecycle) {\n case Lifecycle.Transient:\n return Lifetime.TRANSIENT\n case Lifecycle.Scoped:\n return Lifetime.SCOPED\n case Lifecycle.Singleton:\n default:\n return Lifetime.SINGLETON\n }\n }\n\n /** @inheritdoc */\n registerValue<T>(token: symbol, value: T): void {\n this.ensureInitializedSync()\n const { asValue } = this.awilix!\n const name = this.getTokenName(token)\n this.container.register({\n [name]: asValue(value),\n })\n }\n\n /** @inheritdoc */\n registerFactory<T>(token: symbol, factory: (provider: ContainerProvider) => T): void {\n this.ensureInitializedSync()\n const { asFunction } = this.awilix!\n const name = this.getTokenName(token)\n this.container.register({\n [name]: asFunction(() => factory(this)).singleton(),\n })\n }\n\n /** @inheritdoc */\n registerClass<T>(\n token: symbol | Constructor<T>,\n impl?: Constructor<T>,\n lifecycle?: ProviderLifecycle,\n ): void {\n this.ensureInitializedSync()\n const { asClass } = this.awilix!\n const name = this.getTokenName(token)\n const ClassToRegister = impl ?? (token as Constructor<T>)\n const lifetime = this.mapLifecycle(lifecycle)\n\n this.container.register({\n [name]: asClass(ClassToRegister).setLifetime(lifetime),\n })\n }\n\n /** @inheritdoc */\n isRegistered(token: symbol | Constructor): boolean {\n this.ensureInitializedSync()\n const name = this.getTokenName(token)\n return this.container.hasRegistration(name)\n }\n\n /** @inheritdoc */\n resolve<T>(token: symbol | Constructor<T>): T {\n this.ensureInitializedSync()\n const name = this.getTokenName(token)\n return this.container.resolve<T>(name)\n }\n\n /** @inheritdoc */\n createScope(): ContainerProvider {\n this.ensureInitializedSync()\n const scopedContainer = this.container.createScope()\n const scopedProvider = AwilixProvider.createSync(this.awilix!, {\n container: scopedContainer,\n })\n this.tokenToName.forEach((name, token) => {\n scopedProvider.tokenToName.set(token, name)\n })\n return scopedProvider\n }\n\n /** @inheritdoc */\n dispose(): void {\n if (this.container) {\n this.container.dispose()\n }\n }\n\n /**\n * Returns the underlying Awilix container instance\n * @returns The AwilixContainer instance\n */\n getUnderlyingContainer(): AwilixContainer {\n this.ensureInitializedSync()\n return this.container\n }\n}\n\n","/**\n * InversifyJS Provider Adapter for WireDI\n *\n * This adapter allows using InversifyJS as the DI container backend.\n * InversifyJS is a powerful and lightweight inversion of control container\n * for JavaScript & Node.js apps powered by TypeScript.\n *\n * @remarks\n * Classes registered with this provider must be decorated with `@injectable()`.\n * The provider supports lazy initialization or synchronous initialization via `createSync()`.\n *\n * @example Basic usage with lazy initialization\n * ```typescript\n * import { useContainerProvider, InversifyProvider } from '@djodjonx/wiredi'\n *\n * const provider = new InversifyProvider()\n * await provider.init()\n * useContainerProvider(provider)\n * ```\n *\n * @example Synchronous initialization (recommended)\n * ```typescript\n * import 'reflect-metadata'\n * import * as inversify from 'inversify'\n * import { useContainerProvider, InversifyProvider } from '@djodjonx/wiredi'\n *\n * useContainerProvider(InversifyProvider.createSync(inversify))\n * ```\n *\n * @example With existing container\n * ```typescript\n * import * as inversify from 'inversify'\n * const myContainer = new inversify.Container()\n *\n * useContainerProvider(InversifyProvider.createSync(inversify, {\n * container: myContainer\n * }))\n * ```\n *\n * @see https://github.com/inversify/InversifyJS\n * @module\n */\n\nimport type { Container } from 'inversify'\nimport type { ContainerProvider, ProviderLifecycle } from '../types'\nimport { ProviderLifecycle as Lifecycle } from '../index'\n\n/**\n * Generic constructor type for class instantiation\n * @template T - The type of the class instance\n * @internal\n */\ntype Constructor<T = unknown> = new (...args: unknown[]) => T\n\n/**\n * InversifyJS binding scope options\n * @internal\n */\ntype BindingScope = 'Singleton' | 'Transient' | 'Request'\n\n/**\n * Configuration options for InversifyProvider\n */\nexport interface InversifyProviderOptions {\n /**\n * Existing Inversify container to use\n * If not provided, a new container will be created\n * @default undefined (creates new container)\n */\n container?: Container\n\n /**\n * Default binding scope for registrations without explicit lifecycle\n * @default 'Singleton'\n */\n defaultScope?: BindingScope\n}\n\n/**\n * InversifyJS adapter implementing the ContainerProvider interface\n *\n * Provides integration between WireDI and InversifyJS,\n * allowing you to use InversifyJS as your DI container while benefiting\n * from WireDI's configuration and validation features.\n */\nexport class InversifyProvider implements ContainerProvider {\n /** @inheritdoc */\n readonly name = 'inversify'\n\n /** The InversifyJS container instance */\n private container: Container\n\n /** Default scope for bindings */\n private defaultScope: BindingScope\n\n /** Lazily loaded inversify module */\n private inversify: typeof import('inversify') | null = null\n\n /**\n * Creates a new InversifyProvider instance\n *\n * @param options - Configuration options\n *\n * @remarks\n * When using the constructor directly, you must call `init()` before use,\n * or use `createSync()` for synchronous initialization.\n */\n constructor(private options: InversifyProviderOptions = {}) {\n this.defaultScope = options.defaultScope ?? 'Singleton'\n this.container = null as any\n }\n\n /**\n * Lazily initializes the container (async)\n * @internal\n */\n private async ensureInitialized(): Promise<void> {\n if (this.container) return\n\n this.inversify = await import('inversify')\n this.container = this.options.container ?? new this.inversify.Container()\n }\n\n /**\n * Throws if container is not initialized\n * @internal\n */\n private ensureInitializedSync(): void {\n if (!this.container) {\n throw new Error(\n '[InversifyProvider] Container not initialized. ' +\n 'Call await provider.init() first, or pass a pre-created container in options.'\n )\n }\n }\n\n /**\n * Initializes the provider asynchronously\n *\n * @remarks\n * Required before using the provider if not using `createSync()`.\n *\n * @example\n * ```typescript\n * const provider = new InversifyProvider()\n * await provider.init()\n * useContainerProvider(provider)\n * ```\n */\n async init(): Promise<void> {\n await this.ensureInitialized()\n }\n\n /**\n * Creates a pre-initialized provider synchronously\n *\n * @param inversify - The inversify module import\n * @param options - Configuration options\n * @returns Fully initialized InversifyProvider instance\n *\n * @remarks\n * This is the recommended way to create an InversifyProvider as it\n * avoids async initialization and ensures the provider is ready immediately.\n *\n * @example\n * ```typescript\n * import * as inversify from 'inversify'\n *\n * const provider = InversifyProvider.createSync(inversify, {\n * defaultScope: 'Transient'\n * })\n * ```\n */\n static createSync(inversify: typeof import('inversify'), options: InversifyProviderOptions = {}): InversifyProvider {\n const provider = new InversifyProvider(options)\n provider.inversify = inversify\n provider.container = options.container ?? new inversify.Container()\n return provider\n }\n\n /**\n * Maps WireDI lifecycle to InversifyJS binding scope\n * @internal\n */\n private mapLifecycle(lifecycle?: ProviderLifecycle): BindingScope {\n switch (lifecycle) {\n case Lifecycle.Transient:\n return 'Transient'\n case Lifecycle.Scoped:\n return 'Request'\n case Lifecycle.Singleton:\n default:\n return 'Singleton'\n }\n }\n\n /**\n * Applies the scope to an InversifyJS binding\n * @internal\n */\n private applyScope(\n binding: {\n inSingletonScope(): unknown\n inTransientScope(): unknown\n inRequestScope(): unknown\n },\n scope: BindingScope,\n ): void {\n switch (scope) {\n case 'Singleton':\n binding.inSingletonScope()\n break\n case 'Transient':\n binding.inTransientScope()\n break\n case 'Request':\n binding.inRequestScope()\n break\n }\n }\n\n /** @inheritdoc */\n registerValue<T>(token: symbol, value: T): void {\n this.ensureInitializedSync()\n\n if (this.container.isBound(token)) {\n this.container.unbind(token)\n }\n this.container.bind(token).toConstantValue(value)\n }\n\n /** @inheritdoc */\n registerFactory<T>(token: symbol, factory: (provider: ContainerProvider) => T): void {\n this.ensureInitializedSync()\n\n if (this.container.isBound(token)) {\n this.container.unbind(token)\n }\n this.container.bind(token).toDynamicValue(() => factory(this))\n }\n\n /** @inheritdoc */\n registerClass<T>(\n token: symbol | Constructor<T>,\n impl?: Constructor<T>,\n lifecycle?: ProviderLifecycle,\n ): void {\n this.ensureInitializedSync()\n\n const ClassToRegister = impl ?? (token as Constructor<T>)\n const scope = this.mapLifecycle(lifecycle)\n\n if (this.container.isBound(token)) {\n this.container.unbind(token)\n }\n\n const binding = this.container.bind(token).to(ClassToRegister)\n this.applyScope(binding, scope)\n }\n\n /** @inheritdoc */\n isRegistered(token: symbol | Constructor): boolean {\n this.ensureInitializedSync()\n return this.container.isBound(token)\n }\n\n /** @inheritdoc */\n resolve<T>(token: symbol | Constructor<T>): T {\n this.ensureInitializedSync()\n return this.container.get<T>(token)\n }\n\n /** @inheritdoc */\n createScope(): ContainerProvider {\n this.ensureInitializedSync()\n const childContainer = new this.inversify!.Container()\n return InversifyProvider.createSync(this.inversify!, {\n container: childContainer,\n defaultScope: this.defaultScope,\n })\n }\n\n /** @inheritdoc */\n dispose(): void {\n if (this.container) {\n this.container.unbindAll()\n }\n }\n\n /**\n * Returns the underlying InversifyJS Container instance\n * @returns The InversifyJS Container\n */\n getUnderlyingContainer(): Container {\n this.ensureInitializedSync()\n return this.container\n }\n}\n\n","/**\n * Mutable Event Dispatcher Provider\n *\n * Default implementation of EventDispatcherProvider that stores\n * listeners in memory and resolves them through the DI container.\n *\n * @module\n */\n\nimport type {\n EventDispatcherProvider,\n EventDispatcherProviderOptions,\n EventToken,\n ListenerToken,\n} from './types'\nimport type { ContainerProvider } from '../../Provider'\n\n/**\n * Default EventDispatcherProvider implementation\n *\n * This provider stores listeners in memory and resolves them through the DI container\n * when dispatching events. Each listener must implement an `onEvent(event)` method.\n *\n * @example Basic usage\n * ```typescript\n * import {\n * MutableEventDispatcherProvider,\n * useEventDispatcherProvider,\n * getContainerProvider\n * } from '@djodjonx/wiredi'\n *\n * const eventProvider = new MutableEventDispatcherProvider({\n * containerProvider: getContainerProvider()\n * })\n * useEventDispatcherProvider(eventProvider)\n * ```\n *\n * @example Dispatching events\n * ```typescript\n * const dispatcher = getEventDispatcherProvider()\n * dispatcher.dispatch(new UserCreatedEvent(user))\n * ```\n */\nexport class MutableEventDispatcherProvider implements EventDispatcherProvider {\n /** @inheritdoc */\n readonly name = 'mutable-event-dispatcher'\n\n /** Map of event names to their registered listener tokens */\n private listeners: Map<string, ListenerToken[]> = new Map()\n\n /** DI container provider for resolving listener instances */\n private containerProvider: ContainerProvider\n\n /**\n * Creates a new MutableEventDispatcherProvider instance\n *\n * @param options - Configuration options including the container provider\n */\n constructor(options: EventDispatcherProviderOptions) {\n this.containerProvider = options.containerProvider\n }\n\n /**\n * Extracts the event name from an event token (class constructor)\n * @internal\n */\n private getEventName(eventToken: EventToken): string {\n return eventToken.name\n }\n\n /**\n * Extracts the event name from an event instance\n * @internal\n */\n private getEventNameFromInstance(event: object): string {\n return event.constructor.name\n }\n\n /** @inheritdoc */\n register(eventToken: EventToken, listenerToken: ListenerToken): void {\n const eventName = this.getEventName(eventToken)\n\n if (!this.listeners.has(eventName)) {\n this.listeners.set(eventName, [])\n }\n\n this.listeners.get(eventName)!.push(listenerToken)\n }\n\n /** @inheritdoc */\n dispatch(event: object): void {\n const eventName = this.getEventNameFromInstance(event)\n const listenerTokens = this.listeners.get(eventName) ?? []\n\n for (const listenerToken of listenerTokens) {\n try {\n // ListenerToken can be a symbol or a constructor, both are valid ProviderToken types\n const listener = this.containerProvider.resolve<{ onEvent(event: object): void }>(\n listenerToken as symbol | { new (...args: unknown[]): { onEvent(event: object): void } }\n )\n listener.onEvent(event)\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.stack || error.message : String(error)\n console.error(\n `[MutableEventDispatcherProvider] Error dispatching event \"${eventName}\":`,\n errorMessage\n )\n throw error\n }\n }\n }\n\n /** @inheritdoc */\n hasListeners(eventToken: EventToken): boolean {\n const eventName = this.getEventName(eventToken)\n const listeners = this.listeners.get(eventName)\n return listeners !== undefined && listeners.length > 0\n }\n\n /** @inheritdoc */\n hasListener(eventToken: EventToken, listenerToken: ListenerToken): boolean {\n const eventName = this.getEventName(eventToken)\n const listeners = this.listeners.get(eventName)\n if (!listeners) return false\n return listeners.includes(listenerToken)\n }\n\n /** @inheritdoc */\n clearListeners(eventToken: EventToken): void {\n const eventName = this.getEventName(eventToken)\n this.listeners.delete(eventName)\n }\n\n /** @inheritdoc */\n clearAllListeners(): void {\n this.listeners.clear()\n }\n\n /**\n * Returns the internal listeners map\n * @returns Map of event names to listener tokens\n */\n getUnderlyingDispatcher(): Map<string, ListenerToken[]> {\n return this.listeners\n }\n}\n\n","/**\n * Event Dispatcher Provider Module\n *\n * Provides global management of the event dispatcher provider.\n * The event dispatcher is optional - if not configured, event listeners\n * in builder configurations are silently ignored.\n *\n * @module\n */\n\nimport type { EventDispatcherProvider } from './types'\n\nexport type {\n EventDispatcherProvider,\n EventDispatcherProviderOptions,\n EventToken,\n ListenerToken,\n EventListenerEntry,\n} from './types'\n\nexport { MutableEventDispatcherProvider } from './MutableEventDispatcherProvider'\n\n/**\n * Currently configured global event dispatcher provider\n * @internal\n */\nlet globalEventDispatcherProvider: EventDispatcherProvider | null = null\n\n/**\n * Sets the global EventDispatcherProvider instance\n *\n * Call this once at application startup after setting up the container provider.\n * The event dispatcher uses the container provider to resolve listener instances.\n *\n * @param provider - The EventDispatcherProvider implementation to use\n * @throws Error if a provider is already registered\n *\n * @example\n * ```typescript\n * import {\n * useContainerProvider,\n * TsyringeProvider,\n * useEventDispatcherProvider,\n * MutableEventDispatcherProvider,\n * getContainerProvider\n * } from '@djodjonx/wiredi'\n *\n * // 1. Setup DI container first\n * useContainerProvider(new TsyringeProvider({ container, Lifecycle }))\n *\n * // 2. Setup event dispatcher (optional)\n * useEventDispatcherProvider(new MutableEventDispatcherProvider({\n * containerProvider: getContainerProvider()\n * }))\n * ```\n */\nexport function useEventDispatcherProvider(provider: EventDispatcherProvider): void {\n if (globalEventDispatcherProvider !== null) {\n throw new Error(\n `[EventDispatcher] Provider already registered: \"${globalEventDispatcherProvider.name}\". ` +\n `Cannot register \"${provider.name}\". Call resetEventDispatcherProvider() first if you need to change it.`\n )\n }\n globalEventDispatcherProvider = provider\n}\n\n/**\n * Retrieves the currently registered EventDispatcherProvider\n *\n * @returns The registered EventDispatcherProvider instance\n * @throws Error if no provider has been registered\n *\n * @example\n * ```typescript\n * const eventDispatcher = getEventDispatcherProvider()\n * eventDispatcher.dispatch(new UserCreatedEvent(user))\n * ```\n */\nexport function getEventDispatcherProvider(): EventDispatcherProvider {\n if (globalEventDispatcherProvider === null) {\n throw new Error(\n '[EventDispatcher] No provider registered. ' +\n 'Call useEventDispatcherProvider() at application startup.'\n )\n }\n return globalEventDispatcherProvider\n}\n\n/**\n * Checks if an EventDispatcherProvider has been registered\n *\n * @returns `true` if a provider is registered, `false` otherwise\n *\n * @example\n * ```typescript\n * if (hasEventDispatcherProvider()) {\n * getEventDispatcherProvider().dispatch(event)\n * }\n * ```\n */\nexport function hasEventDispatcherProvider(): boolean {\n return globalEventDispatcherProvider !== null\n}\n\n/**\n * Resets the global EventDispatcherProvider\n *\n * Clears all registered listeners and removes the provider.\n * Useful for testing or reconfiguration scenarios.\n *\n * ⚠️ WARNING: This should rarely be used in production code.\n *\n * @example\n * ```typescript\n * // In a test file\n * afterEach(() => {\n * resetEventDispatcherProvider()\n * })\n * ```\n */\nexport function resetEventDispatcherProvider(): void {\n if (globalEventDispatcherProvider !== null) {\n globalEventDispatcherProvider.clearAllListeners()\n }\n globalEventDispatcherProvider = null\n}\n\n","import {\n getContainerProvider,\n type ContainerProvider,\n ProviderLifecycle,\n} from './Provider/index'\nimport {\n getEventDispatcherProvider,\n hasEventDispatcherProvider,\n} from './EventDispatcher/Provider/index'\n\n// Re-export Provider API\nexport {\n useContainerProvider,\n getContainerProvider,\n hasContainerProvider,\n resetContainerProvider,\n TsyringeProvider,\n AwilixProvider,\n InversifyProvider,\n ProviderLifecycle,\n} from './Provider/index'\n\nexport type {\n ContainerProvider,\n ProviderToken,\n ProviderAdapterOptions,\n TsyringeProviderOptions,\n TsyringeDependencies,\n TsyringeDependencyContainer,\n TsyringeLifecycle,\n AwilixProviderOptions,\n InversifyProviderOptions,\n} from './Provider/index.ts'\n\n// Re-export EventDispatcher Provider API\nexport {\n useEventDispatcherProvider,\n getEventDispatcherProvider,\n hasEventDispatcherProvider,\n resetEventDispatcherProvider,\n MutableEventDispatcherProvider,\n} from './EventDispatcher/Provider/index'\n\nexport type {\n EventDispatcherProvider,\n EventDispatcherProviderOptions,\n EventToken,\n ListenerToken,\n EventListenerEntry,\n} from './EventDispatcher/Provider/index'\n\n// Generic constructor type - 'any[]' is required for constructor args compatibility\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Constructor<T = unknown> = new (...args: any[]) => T\n\n/**\n * Value injection entry - registers a static value for a token\n * @template C - Context type passed to the value function\n * @template T - Type of the value returned\n */\ninterface BuilderConfigEntryValue<C = null, T = unknown> {\n token: symbol\n value: (context?: C) => T\n}\n\n/**\n * Injection with symbol token and provider class\n * @template T - Type of the instance created by the provider\n */\ninterface BuilderConfigEntryInjectionWithToken<T = unknown> {\n token: symbol\n provider: Constructor<T>\n lifecycle?: ProviderLifecycle\n}\n\n/**\n * Injection using a class as both token and provider\n */\ninterface BuilderConfigEntryInjectionWithClass {\n token: Constructor\n lifecycle?: ProviderLifecycle\n}\n\n/**\n * Factory injection entry - registers a factory function for a token\n * @template T - Type of the instance returned by the factory\n */\ninterface BuilderConfigEntryFactory<T = unknown> {\n token: symbol\n factory: (provider: ContainerProvider) => T\n}\n\ntype BuilderConfigEntries<C> = BuilderConfigEntryValue<C, unknown>\n | BuilderConfigEntryInjectionWithToken<unknown>\n | BuilderConfigEntryFactory<unknown>\n | BuilderConfigEntryInjectionWithClass\n\n\nexport type InjectionConfig<C> = readonly BuilderConfigEntries<C>[]\n\ninterface EventEntry {\n event: Constructor\n listener: Constructor\n}\n\n\nexport type EventConfig = readonly EventEntry[]\n\nexport interface BuilderConfig<C = null> {\n builderId: string\n injections: InjectionConfig<C>\n listeners?: EventConfig\n}\n\n/**\n * A partial builder configuration that defines a set of injections and listeners.\n * Partials are \"traits\" or \"mixins\" that can be composed into a main `BuilderConfig`.\n *\n * NOTE: Partials cannot extend other partials to prevent hidden dependency chains.\n */\nexport interface PartialBuilderConfig<C = null> {\n injections?: InjectionConfig<C>\n listeners?: EventConfig\n}\n\ntype ResolveToken<T> = symbol | Constructor<T>\n\n/**\n * Type guard to check if a token is a constructor (class).\n * @param token The token to check.\n * @returns True if the token is a constructor, false otherwise.\n */\nfunction isConstructor<T = any>(token: unknown): token is Constructor<T> {\n return typeof token === 'function'\n && !!(token as Constructor).prototype\n && (token as Constructor).prototype.constructor === token\n}\n\n/**\n * Helper type to extract the tuple of tokens from the injections config.\n */\ntype ExtractTokens<T> = {\n [K in keyof T]: T[K] extends { token: infer Token } ? Token : never\n}\n\n/**\n * A builder configuration with strictly inferred token types.\n * @template C The context type.\n * @template Tokens The tuple of allowed tokens.\n */\nexport interface TypedBuilderConfig<C, Tokens> extends BuilderConfig<C> {\n // Phantom property to carry the inferred tokens type for the IDE\n readonly __tokens?: Tokens\n}\n\n/**\n * A partial builder configuration with strictly inferred token types.\n * @template C The context type.\n * @template Tokens The tuple of allowed tokens.\n * @template Listeners The tuple of listener entries.\n */\nexport interface TypedPartialConfig<C, Tokens, Listeners = readonly EventEntry[]> extends PartialBuilderConfig<C> {\n readonly __tokens?: Tokens\n readonly __listeners?: Listeners\n}\n\n/**\n * Interface for the return object of `useBuilder`, providing a `resolve` method.\n * The `AllowedTokens` generic parameter strictly types which tokens can be resolved.\n */\ninterface IUseBuilder<AllowedTokens = ResolveToken<any>> {\n /**\n * Resolves a class dependency.\n * The return type is automatically inferred as the class instance.\n *\n * @template Token The class constructor type (inferred from argument).\n * @param token The class constructor token.\n * @returns The instance of the class.\n */\n resolve<Token extends Extract<AllowedTokens, Constructor<any>>>(token: Token): InstanceType<Token>\n\n /**\n * Resolves a dependency from the container (for Symbols or explicit types).\n *\n * @template T The type of the dependency to resolve.\n * @param token The token (symbol or constructor) of the dependency.\n * This is strictly type-checked against the `injections` defined in the builder config.\n * @returns The resolved instance of the dependency.\n */\n resolve<T>(token: AllowedTokens & ResolveToken<T>): T\n}\n\nfunction registerConfig<C = null>(\n provider: ContainerProvider,\n injections: InjectionConfig<C>,\n context?: C,\n): void {\n injections.forEach(entry => {\n if (provider.isRegistered(entry.token)) return\n\n if ('value' in entry) {\n // Value injection\n provider.registerValue(entry.token, entry.value(context))\n } else if ('factory' in entry) {\n // Factory injection\n provider.registerFactory(entry.token, () => entry.factory(provider))\n } else if (isConstructor(entry.token)) {\n // Class token (token is the class itself)\n const lifecycle = entry.lifecycle ?? ProviderLifecycle.Singleton\n provider.registerClass(entry.token, entry.token, lifecycle)\n } else {\n // Symbol token with provider class\n if (!('provider' in entry)) {\n throw new Error(`Provider required when registering token Symbol: ${String(entry.token)}`)\n }\n const lifecycle = entry.lifecycle ?? ProviderLifecycle.Singleton\n provider.registerClass(entry.token, entry.provider, lifecycle)\n }\n })\n}\n\n\nfunction registerEvent(\n _provider: ContainerProvider,\n listeners?: EventConfig,\n): void {\n if (!listeners || !listeners.length) return\n\n // Check if event dispatcher provider is configured\n if (!hasEventDispatcherProvider()) {\n // Silently skip if no event dispatcher is configured\n // This allows using WireDI without events\n return\n }\n\n const eventDispatcher = getEventDispatcherProvider()\n\n listeners.forEach((configEntry) => {\n if (!eventDispatcher.hasListener(configEntry.event, configEntry.listener)) {\n eventDispatcher.register(configEntry.event, configEntry.listener)\n }\n })\n}\n\n/**\n * Helper to define a partial configuration (injections/listeners).\n *\n * Partials are designed to be flat collections of dependencies. They do not support\n * inheritance (`extends`) or overriding to prevent complex dependency graphs.\n * All conflict resolution must happen in the main `defineBuilderConfig`.\n *\n * @template C The type of the context object (optional).\n * @template I The specific type of the injections array (inferred).\n * @param config The partial builder configuration object.\n * @returns The configuration object typed as TypedPartialConfig.\n */\nexport function definePartialConfig<\n C = null,\n const I extends InjectionConfig<C> = InjectionConfig<C>,\n const L extends EventConfig = EventConfig,\n>(\n config: PartialBuilderConfig<C> & { injections?: I, listeners?: L },\n): TypedPartialConfig<C, ExtractTokens<I>, L> {\n return config as TypedPartialConfig<C, ExtractTokens<I>, L>\n}\n\n// --- Type Helpers for `defineBuilderConfig` Extension Logic ---\n\n/**\n * Recursively extracts tokens from a tuple of TypedPartialConfigs.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ExtractTokensFromTypedPartials<T extends readonly TypedPartialConfig<any, any, any>[]> =\n T extends readonly [infer Head, ...infer Tail]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ? Tail extends readonly TypedPartialConfig<any, any, any>[]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ? Head extends TypedPartialConfig<any, infer Tokens, any>\n ? Tokens extends readonly unknown[]\n ? [...Tokens, ...ExtractTokensFromTypedPartials<Tail>]\n : ExtractTokensFromTypedPartials<Tail>\n : ExtractTokensFromTypedPartials<Tail>\n : []\n : []\n\n/**\n * Helper to extract (Event, Listener) pairs from partials for duplicate checking.\n * Uses the __listeners type parameter from TypedPartialConfig.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ExtractListenersFromPartials<T extends readonly TypedPartialConfig<any, any, any>[]> =\n T extends readonly [infer Head, ...infer Tail]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ? Tail extends readonly TypedPartialConfig<any, any, any>[]\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ? Head extends TypedPartialConfig<any, any, infer Listeners>\n ? Listeners extends readonly (infer L)[]\n ? L | ExtractListenersFromPartials<Tail>\n : ExtractListenersFromPartials<Tail>\n : ExtractListenersFromPartials<Tail>\n : never\n : never\n\n/**\n * Validates that injections do not collide with tokens from inherited partials.\n *\n * Rules:\n * 1. Token exists in Partial -> ❌ Error: Token collision (duplicates not allowed)\n * 2. Token NOT in Partial -> ✅ Valid New Entry\n * 3. Token duplicated in same array -> ❌ Error: Internal duplication\n *\n * Note: Token overrides are not allowed. Each token must be unique across all partials\n * and the main configuration. This prevents accidental redefinition of dependencies.\n */\ntype ValidateInjections<LocalInjections, InheritedTokenUnion> =\n [InheritedTokenUnion] extends [never]\n // No inherited tokens, validate only internal duplicates\n ? ValidateInjectionsInternal<LocalInjections>\n : ValidateInjectionsInternal<ValidateAgainstPartials<LocalInjections, InheritedTokenUnion>>\n\n/**\n * Validates injections against inherited tokens from partials.\n *\n * Note: Plain symbols are skipped because TypeScript sees all Symbol() as the same type.\n * Use branded symbols or class tokens for proper partial validation.\n */\ntype ValidateAgainstPartials<LocalInjections, InheritedTokenUnion> = {\n [K in keyof LocalInjections]: LocalInjections[K] extends { token: infer T }\n ? T extends symbol\n ? symbol extends T\n ? LocalInjections[K] // Plain symbol - skip validation\n : T extends InheritedTokenUnion // Branded symbol - validate\n ? {\n error: '[WireDI] This token is already registered in a partial. Remove it from here or from the partial to avoid conflicts.'\n token: T\n hint: 'Each token can only be registered once across all partials and the main config.'\n }\n : LocalInjections[K]\n : T extends InheritedTokenUnion // Class or other token - validate\n ? {\n error: '[WireDI] This token is already registered in a partial. Remove it from here or from the partial to avoid conflicts.'\n token: T\n hint: 'Each token can only be registered once across all partials and the main config.'\n }\n : LocalInjections[K]\n : LocalInjections[K]\n}\n\n/**\n * Validates that there are no duplicate tokens within the same injections array.\n * Checks each token against all following entries.\n *\n * Note: Plain symbols (Symbol('x')) are skipped because TypeScript sees them all as type 'symbol'.\n * For duplicate detection with symbols, use branded symbols: Symbol('x') as symbol & { __brand: 'x' }\n */\ntype ValidateInjectionsInternal<T> = T extends readonly []\n ? T\n : T extends readonly [infer First, ...infer Rest]\n ? First extends { token: infer Token }\n ? IsPlainSymbol<Token> extends true\n ? [First, ...ValidateInjectionsInternal<Rest>] // Skip plain symbols\n : HasTokenDuplicate<Token, Rest> extends true\n ? [\n {\n error: '[WireDI] Duplicate token in the same configuration'\n token: Token\n hint: 'Each token can only be registered once. Remove one of the duplicate entries.'\n },\n ...ValidateInjectionsInternal<Rest>\n ]\n : [First, ...ValidateInjectionsInternal<Rest>]\n : [First, ...ValidateInjectionsInternal<Rest>]\n : T\n\n/**\n * Checks if a type is a plain symbol (not branded).\n * Plain symbols are Symbol() without intersection types.\n */\ntype IsPlainSymbol<T> = T extends symbol\n ? symbol extends T\n ? true // T is exactly 'symbol' (plain, not branded)\n : false // T is a branded symbol (symbol & { ... })\n : false // T is not a symbol at all\n\n/**\n * Helper to check if a token exists in the rest of the array.\n * Uses strict type equality to avoid false positives.\n *\n * Note: Plain symbols without branding (e.g., Symbol('x')) are all seen as 'symbol' type\n * by TypeScript, so we skip duplicate detection for plain symbols to avoid false positives.\n * For proper token validation, use branded symbols or class tokens.\n */\ntype HasTokenDuplicate<Token, Rest> =\n // Skip duplicate detection for plain symbols (they're all the same type to TS)\n Token extends symbol\n ? symbol extends Token\n ? false // Plain symbol without branding - skip detection\n : HasTokenDuplicateCheck<Token, Rest> // Branded symbol - check for duplicates\n : HasTokenDuplicateCheck<Token, Rest> // Class or other token - check for duplicates\n\ntype HasTokenDuplicateCheck<Token, Rest> = Rest extends readonly [infer First, ...infer Tail]\n ? First extends { token: infer T }\n ? StrictEquals<Token, T> extends true\n ? true\n : HasTokenDuplicateCheck<Token, Tail>\n : HasTokenDuplicateCheck<Token, Tail>\n : false\n\n/**\n * Validates that local listeners do not duplicate listeners already defined in partials.\n * Duplicate = Same Event class AND Same Listener class.\n *\n * Applies both:\n * 1. Internal duplicate detection (within same array)\n * 2. Partial collision detection (against inherited listeners)\n */\ntype ValidateListeners<LocalListeners, InheritedListenerUnion> =\n [InheritedListenerUnion] extends [never]\n // No inherited listeners, validate only internal duplicates\n ? ValidateListenersInternal<LocalListeners>\n // Has inherited listeners, validate both internal and against partials\n : ValidateListenersInternal<ValidateListenersAgainstPartialsFixed<LocalListeners, InheritedListenerUnion>>\n\n/**\n * Check each local listener against inherited listeners from partials.\n * Only flags entries where BOTH event AND listener match exactly.\n */\ntype ValidateListenersAgainstPartialsFixed<LocalListeners, InheritedListenerUnion> = {\n [K in keyof LocalListeners]: LocalListeners[K] extends { event: infer E, listener: infer L }\n ? true extends CheckListenerInUnionDistributive<E, L, InheritedListenerUnion>\n ? {\n error: '[WireDI] This event listener is already registered in a partial'\n event: E\n listener: L\n hint: 'Each (event, listener) pair can only be registered once.'\n }\n : LocalListeners[K]\n : LocalListeners[K]\n}\n\n/**\n * Check if a (event, listener) pair exists in a union.\n * Distributes over the union to check each member.\n * Uses StrictEquals for exact type comparison.\n */\ntype CheckListenerInUnionDistributive<E, L, Union> =\n Union extends { event: infer UE, listener: infer UL }\n ? StrictEquals<E, UE> extends true\n ? StrictEquals<L, UL> extends true\n ? true\n : false\n : false\n : false\n\n\n/**\n * Strict type equality check.\n * Returns true only if A and B are exactly the same type.\n */\ntype StrictEquals<A, B> =\n (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false\n\n/**\n * Validates that there are no duplicate listeners within the same array.\n * Checks each listener against all following listeners.\n * A duplicate is defined as having BOTH the same event AND the same listener.\n */\ntype ValidateListenersInternal<T> = T extends readonly []\n ? T\n : T extends readonly [infer First, ...infer Rest]\n ? First extends { event: infer E, listener: infer L }\n ? HasExactDuplicate<E, L, Rest> extends true\n ? [\n {\n error: '[WireDI] Duplicate listener in the same configuration'\n event: E\n listener: L\n hint: 'Each (event, listener) pair must be unique within the configuration.'\n },\n ...ValidateListenersInternal<Rest>\n ]\n : [First, ...ValidateListenersInternal<Rest>]\n : [First, ...ValidateListenersInternal<Rest>]\n : T\n\n/**\n * Helper to check if an exact (event, listener) pair exists in the rest of the array.\n * Uses strict type equality to avoid false positives with structurally similar types.\n */\ntype HasExactDuplicate<E, L, Rest> = Rest extends readonly [infer First, ...infer Tail]\n ? First extends { event: infer FE, listener: infer FL }\n ? StrictEquals<E, FE> extends true\n ? StrictEquals<L, FL> extends true\n ? true\n : HasExactDuplicate<E, L, Tail>\n : HasExactDuplicate<E, L, Tail>\n : HasExactDuplicate<E, L, Tail>\n : false\n\n/**\n * A helper function to define a builder configuration with strict type inference and inheritance.\n * Use this instead of manually casting with `satisfies BuilderConfig` or `as const`\n * to ensure that `useBuilder` can correctly infer the available tokens.\n *\n * This function now supports `extends` to inherit from `definePartialConfig` definitions.\n * Token collisions are strictly forbidden - each token must be unique across all partials\n * and the main configuration to prevent accidental redefinition.\n *\n * @template C The type of the context object (optional).\n * @template Partials The tuple of partial configs to extend.\n * @template LocalInjections The specific type of the local injections array (inferred).\n * @param config The builder configuration object.\n * @returns The configuration object typed as TypedBuilderConfig to simplify IDE display.\n *\n * @example\n * ```typescript\n * import { Lifecycle } from 'tsyringe';\n *\n * class MyService {}\n * class MyProvider {}\n * class MyEvent {}\n * class MyEventListener {\n * onEvent(event: MyEvent) {\n * console.log('Event received:', event);\n * }\n * }\n *\n * const MY_TOKEN = Symbol('MY_TOKEN');\n * const MY_VALUE_TOKEN = Symbol('MY_VALUE_TOKEN');\n * const MY_FACTORY_TOKEN = Symbol('MY_FACTORY_TOKEN');\n *\n * // --- Partial Configuration ---\n * const myPartial = definePartialConfig({\n * injections: [\n * { token: MyService } // Provides MyService\n * ],\n * listeners: [\n * { event: MyEvent, listener: MyEventListener }\n * ]\n * });\n *\n * // --- Main Builder Configuration ---\n * const myBuilderConfig = defineBuilderConfig({\n * builderId: 'my.unique.builder',\n * extends: [myPartial],\n * injections: [\n * // ❌ ERROR: Token collision - MyService is already defined in myPartial\n * // { token: MyService },\n *\n * // ✅ OK: New tokens not in partials\n * { token: MY_TOKEN, provider: MyProvider },\n * { token: MY_TOKEN, provider: MyProvider, lifecycle: Lifecycle.Transient },\n *\n * // 3. Value Injection (can use optional context)\n * { token: MY_VALUE_TOKEN, value: (context) => context?.someConfig ?? 'defaultValue' },\n *\n * // 4. Factory Injection\n * { token: MY_FACTORY_TOKEN, factory: (container) => new MyService() },\n * ],\n * listeners: [\n * // ❌ ERROR: Duplicate listener (Event + Listener pair already in myPartial)\n * // { event: MyEvent, listener: MyEventListener },\n *\n * // ✅ OK: New listener not in partials\n * { event: OtherEvent, listener: OtherEventListener },\n * ],\n * });\n *\n * // Usage:\n * // const { resolve } = useBuilder(myBuilderConfig, { someConfig: 'custom' });\n * // const service = resolve(MyService);\n * // const value = resolve(MY_VALUE_TOKEN);\n * ```\n */\nexport function defineBuilderConfig<\n C = null,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const Partials extends readonly TypedPartialConfig<C, any, any>[] = [],\n const LocalInjections extends InjectionConfig<C> = InjectionConfig<C>,\n const LocalListeners extends EventConfig | undefined = EventConfig | undefined,\n>(\n config: {\n builderId: string\n extends?: Partials\n injections: ValidateInjections<LocalInjections, ExtractTokensFromTypedPartials<Partials>[number]>\n listeners?: ValidateListeners<LocalListeners, ExtractListenersFromPartials<Partials>>\n },\n): TypedBuilderConfig<C, [...ExtractTokensFromTypedPartials<Partials>, ...ExtractTokens<LocalInjections>]> {\n // Runtime Logic:\n // We place local injections FIRST.\n // Since `registerConfig` checks `if (container.isRegistered(entry.token)) return`,\n // the first occurrence of a token wins. This effectively implements the override logic.\n const mergedInjections = [\n ...config.injections as InjectionConfig<C>,\n ...(config.extends || []).flatMap(p => p.injections || []),\n ]\n\n const mergedListeners = [\n ...(config.extends || []).flatMap(p => p.listeners || []),\n ...(config.listeners as EventConfig || []),\n ]\n\n return {\n ...config,\n injections: mergedInjections,\n listeners: mergedListeners,\n } as any\n}\n\n/**\n * A composable function for setting up and interacting with a dependency injection container\n * based on a `BuilderConfig`. It ensures that dependencies are registered only once per builderId\n * and provides a type-safe `resolve` method.\n *\n * The `resolve` method is strictly type-checked to only allow tokens defined within the `injections`\n * array of the provided `config`.\n *\n * ⚠️ Requires `useContainerProvider()` to be called first at app entry point.\n *\n * @template C The type of the context object that might be passed to value providers.\n * @template Tokens The inferred tuple of allowed tokens from the config.\n * @param config The typed builder configuration object.\n * @param context An optional context object that can be passed to value providers in the injections.\n * @returns An `IUseBuilder` instance with a type-safe `resolve` method.\n *\n * @example\n * ```typescript\n * // main.ts - Entry point\n * import { useContainerProvider, TsyringeProvider } from '@djodjonx/wiredi'\n * useContainerProvider(new TsyringeProvider())\n *\n * // anywhere.ts\n * import { useBuilder } from '@djodjonx/wiredi'\n * const { resolve } = useBuilder(myConfig)\n * const service = resolve(MyService)\n * ```\n */\nexport function useBuilder<C = null, Tokens extends readonly any[] = []>(\n config: TypedBuilderConfig<C, Tokens>,\n context?: C,\n): IUseBuilder<Tokens[number]> {\n const provider = getContainerProvider()\n\n // Use builderId as a marker to ensure we only register once\n const builderIdToken = Symbol.for(`__builder__${config.builderId}`)\n\n if (!provider.isRegistered(builderIdToken)) {\n registerConfig(provider, config.injections, context)\n registerEvent(provider, config.listeners)\n provider.registerValue(builderIdToken, config.builderId)\n }\n\n const resolve = <T>(token: ResolveToken<T> & Tokens[number]): T => provider.resolve<T>(token)\n\n return {\n resolve,\n }\n}\n"],"mappings":"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"}
|