@navios/di 0.6.1 → 0.7.1
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/CHANGELOG.md +47 -0
- package/lib/browser/index.d.mts +15 -84
- package/lib/browser/index.d.mts.map +1 -1
- package/lib/browser/index.mjs +121 -484
- package/lib/browser/index.mjs.map +1 -1
- package/lib/{index-DW3K5sOX.d.cts → container-BuAutHGg.d.mts} +17 -62
- package/lib/container-BuAutHGg.d.mts.map +1 -0
- package/lib/{testing-DIaIRiJz.cjs → container-DnzgpfBe.cjs} +81 -459
- package/lib/container-DnzgpfBe.cjs.map +1 -0
- package/lib/{testing-BG_fa9TJ.mjs → container-Pb_Y4Z4x.mjs} +81 -446
- package/lib/container-Pb_Y4Z4x.mjs.map +1 -0
- package/lib/{index-7jfWsiG4.d.mts → container-oGTgX2iX.d.cts} +12 -67
- package/lib/container-oGTgX2iX.d.cts.map +1 -0
- package/lib/index.cjs +44 -52
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +6 -25
- package/lib/index.d.cts.map +1 -1
- package/lib/index.d.mts +6 -25
- package/lib/index.d.mts.map +1 -1
- package/lib/index.mjs +2 -2
- package/lib/testing/index.cjs +343 -4
- package/lib/testing/index.cjs.map +1 -0
- package/lib/testing/index.d.cts +65 -2
- package/lib/testing/index.d.cts.map +1 -0
- package/lib/testing/index.d.mts +65 -2
- package/lib/testing/index.d.mts.map +1 -0
- package/lib/testing/index.mjs +341 -2
- package/lib/testing/index.mjs.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/async-local-storage.browser.spec.mts +18 -92
- package/src/__tests__/container.spec.mts +93 -0
- package/src/__tests__/e2e.browser.spec.mts +7 -15
- package/src/__tests__/library-findings.spec.mts +23 -21
- package/src/browser.mts +4 -9
- package/src/container/scoped-container.mts +14 -8
- package/src/index.mts +5 -8
- package/src/internal/context/async-local-storage.browser.mts +19 -0
- package/src/internal/context/async-local-storage.mts +46 -98
- package/src/internal/context/async-local-storage.types.mts +7 -0
- package/src/internal/context/resolution-context.mts +23 -5
- package/src/internal/context/sync-local-storage.mts +3 -1
- package/src/internal/core/instance-resolver.mts +8 -1
- package/src/internal/lifecycle/circular-detector.mts +15 -0
- package/src/token/registry.mts +21 -0
- package/tsdown.config.mts +12 -1
- package/vitest.config.mts +25 -3
- package/lib/index-7jfWsiG4.d.mts.map +0 -1
- package/lib/index-DW3K5sOX.d.cts.map +0 -1
- package/lib/testing-BG_fa9TJ.mjs.map +0 -1
- package/lib/testing-DIaIRiJz.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["SyncLocalStorage","hasAsyncHooksSupport","process","versions","node","globalThis","Deno","AsyncLocalStorageClass","initialized","forceSyncMode","getAsyncLocalStorageClass","asyncHooks","require","AsyncLocalStorage","createAsyncLocalStorage","StorageClass","isUsingNativeAsyncLocalStorage","__testing__","reset","InjectionToken","id","globalThis","crypto","randomUUID","formattedName","name","schema","create","bound","token","value","BoundInjectionToken","factory","FactoryInjectionToken","refineType","toString","className","resolved","resolve","ctx","parent?: Registry","InjectableScope","InjectableType","InjectionToken","globalRegistry","InjectableTokenMeta","Injectable","scope","Singleton","token","schema","registry","target","context","kind","Function","Error","injectableToken","create","set","Class","code: DIErrorCode","message: string","createAsyncLocalStorage","resolutionContext","withResolutionContext","waiterHolder","getHolder","fn","run","getCurrentResolutionContext","getStore","withoutResolutionContext","undefined","InjectableTokenMeta","withoutResolutionContext","getInjectors","currentFactoryContext","provideFactoryContext","context","original","getFactoryContext","Error","promiseCollector","injectState","getRequest","token","args","skipCycleTracking","isFrozen","idx","currentIndex","request","requests","toString","result","error","doInject","inject","then","r","catch","e","promise","push","asyncInject","realToken","wrapSyncInit","cb","previousState","promises","originalPromiseCollector","originalInjectState","newInjectState","instance","container","tryGetSync","Proxy","get","optional","injectors","InjectableTokenMeta","getInjectableToken","target","token","Error","name","asyncInject: Injectors['asyncInject']","inject: Injectors['inject']","optional: Injectors['optional']","wrapSyncInit: Injectors['wrapSyncInit']","provideFactoryContext: Injectors['provideFactoryContext']","CircularDetector","detectCycle","waiterName","targetName","getHolder","visited","Set","queue","name","path","length","currentName","shift","has","add","holder","waitingForName","waitingFor","push","formatCycle","cycle","join","DIError","CircularDetector","InstanceStatus","BaseHolderManager","_holders","logger","Map","holders","delete","name","filter","predicate","key","value","clear","size","createCreatingHolder","type","scope","deps","Set","deferred","Promise","withResolvers","holder","status","Creating","instance","creationPromise","promise","destroyPromise","destroyListeners","createdAt","Date","now","waitingFor","createCreatedHolder","Created","getAllNames","Array","from","keys","getAllHolders","values","isEmpty","waitForHolderReady","waiterHolder","getHolder","cycle","detectCycle","circularDependency","add","Destroying","instanceDestroying","Error","undefined","instanceNotFound","BaseHolderManager","InjectableScope","InjectableType","InjectionToken","DefaultRequestContext","metadata","Map","createdAt","Date","now","requestId","priority","initialMetadata","Object","entries","forEach","key","value","set","holders","_holders","get","name","holder","has","addInstance","instanceName","instance","toString","createdHolder","createCreatedHolder","Class","Singleton","Set","Error","clear","getMetadata","setMetadata","createRequestContext","contextHolder: RequestContext","holderManager: BaseHolderManager","names: string[]","dependents: string[]","BaseHolderManager","InjectableScope","DIError","DefaultRequestContext","RequestStorage","InstanceStatus","ScopedContainer","requestContextHolder","holderStorage","disposed","parent","registry","requestId","metadata","priority","getServiceLocator","getManager","getRequestContextHolder","getHolderStorage","getRequestId","getParent","getMetadata","key","setMetadata","value","addInstance","token","instance","get","args","unknown","tokenProcessor","getTokenProcessor","actualToken","normalizeToken","isRequestScoped","resolveRequestScoped","getWithContext","invalidate","service","holder","findByInstance","getInvalidator","invalidateWithStorage","name","emitEvents","isRegistered","dispose","endRequest","clearAllWithStorage","waitForSettlement","maxRounds","clear","removeActiveRequest","ready","tryGetSync","serviceLocator","instanceName","getInstanceIdentifier","status","Created","realToken","getRealToken","has","record","scope","Request","existingHolder","error","readyHolder","waitForHolderReady","resolveForRequest","storeRequestInstance","getRequestInstance","getPrefixedEventName","manager: HolderManager","dependents: string[]","InjectableScope","DIError","DIErrorCode","BoundInjectionToken","FactoryInjectionToken","getCurrentResolutionContext","withResolutionContext","BaseHolderManager","InstanceStatus","SingletonStorage","InstanceResolver","singletonStorage","registry","manager","instantiator","tokenProcessor","logger","serviceLocator","resolveInstance","token","args","contextContainer","resolveWithStorage","resolveRequestScopedInstance","scopedContainer","getHolderStorage","storage","err","data","resolveTokenAndPrepareInstanceName","instanceName","validatedArgs","realToken","getResult","get","error","holder","readyResult","waitForInstanceReady","undefined","instance","handledResult","handleStorageError","createError","createAndStoreInstance","code","InstanceDestroying","log","destroyPromise","newResult","has","factoryNotFound","name","toString","ctx","createFactoryContext","record","scope","type","Transient","createTransientInstance","deferred","createCreatingHolder","deps","set","getHolder","storageResult","storageHolder","managerHolder","instantiateService","then","result","length","handleInstantiationResult","catch","handleInstantiationError","tempHolder","status","Creating","creationPromise","destroyListeners","createdAt","Date","now","waitingFor","Set","Created","getDestroyListeners","getSyncInstance","actualToken","validateAndResolveTokenArgs","generateInstanceName","requestHolder","getRequestInstance","UnknownError","FactoryTokenNotResolved","resolve","waitForHolderReady","waiterHolder","handleInstantiationSuccess","size","forEach","dependency","push","getEventBus","on","getInvalidator","invalidate","prefixedDependency","getPrefixedEventName","Error","Singleton","reject","InjectableType","DIError","Instantiator","injectors","instantiateService","ctx","record","args","undefined","type","Class","instantiateClass","Factory","instantiateFactory","unknown","error","String","tryLoad","wrapSyncInit","original","provideFactoryContext","result","target","instance","promises","injectState","length","results","Promise","allSettled","some","status","name","newRes","console","onServiceInit","addDestroyListener","onServiceDestroy","builder","create","InstanceStatus","SingletonStorage","Invalidator","storage","manager","eventBus","logger","invalidate","service","round","invalidateWithStorage","options","cascade","_invalidating","Set","has","log","result","get","add","optionsWithTracking","dependents","findDependents","dependentName","holder","invalidateHolderWithStorage","clearAll","clearAllWithStorage","maxRounds","waitForSettlement","readyWithStorage","allServiceNames","getAllNames","length","join","clearServicesWithDependencyAwarenessForStorage","ready","holders","forEach","_","push","Promise","all","map","waitForHolderToSettle","key","emitEvents","onInvalidated","invalidateHolderByStatus","context","onCreationError","error","onRecursiveInvalidate","onDestroy","destroyHolderWithStorage","status","Destroying","destroyPromise","Creating","creationPromise","destroyListeners","listener","then","deps","clear","delete","emitInstanceEvent","Created","Error","serviceNames","clearedServices","size","servicesToClearThisRound","findServicesReadyForClearingInStorage","remainingServices","filter","name","warn","forceClearServicesInStorage","clearPromises","serviceName","hasUnclearedDependencies","Array","from","some","dep","promises","event","resolve","emit","LifecycleEventBus","listeners","Map","logger","on","ns","event","listener","debug","has","set","nsEvents","get","Set","add","delete","size","emit","key","events","res","Promise","allSettled","map","then","results","filter","result","status","warn","reason","length","reject","DIError","DIErrorCode","BaseHolderManager","InstanceStatus","HolderManager","logger","get","name","holder","_holders","status","Destroying","log","instanceDestroying","Error","instance","undefined","instanceNotFound","set","has","error","code","InstanceDestroying","storeCreatedHolder","type","scope","deps","Set","createCreatedHolder","DIError","BoundInjectionToken","FactoryInjectionToken","getInjectableToken","TokenProcessor","logger","normalizeToken","token","getRealToken","getRegistryToken","validateAndResolveTokenArgs","args","actualToken","realArgs","value","resolved","factoryTokenNotResolved","name","schema","undefined","validatedArgs","safeParse","success","error","toString","unknown","data","generateInstanceName","formattedArgs","Object","entries","sort","keyA","keyB","localeCompare","map","key","formatArgValue","join","replaceAll","length","JSON","stringify","slice","createFactoryContext","container","onDependencyResolved","destroyListeners","Set","deps","addDestroyListener","listener","add","getDestroyListeners","Array","from","self","inject","instanceName","get","defaultInjectors","InstanceResolver","globalRegistry","Instantiator","Invalidator","LifecycleEventBus","HolderManager","TokenProcessor","ServiceLocator","eventBus","manager","instantiator","tokenProcessor","invalidator","instanceResolver","registry","logger","injectors","getEventBus","getManager","getInvalidator","getTokenProcessor","getInstanceIdentifier","token","args","err","actualToken","validatedArgs","validateAndResolveTokenArgs","generateInstanceName","getInstance","contextContainer","data","resolveInstance","undefined","getOrThrowInstance","error","instance","resolveRequestScoped","scopedContainer","resolveRequestScopedInstance","getSyncInstance","invalidate","service","round","clearAll","options","ready","Injectable","InjectableScope","InjectableType","DIError","defaultInjectors","globalRegistry","ScopedContainer","ServiceLocator","getInjectableToken","Container","registry","logger","injectors","serviceLocator","registerSelf","activeRequestIds","Set","token","instanceName","getInstanceIdentifier","getManager","storeCreatedHolder","Class","Singleton","get","args","tokenProcessor","getTokenProcessor","realToken","getRegistryToken","has","record","scope","Request","unknown","String","name","getOrThrowInstance","getWithContext","contextContainer","resolveForRequest","scopedContainer","resolveRequestScoped","getServiceLocator","getRegistry","invalidate","service","holder","getHolderByInstance","instance","holderMap","Array","from","filter","values","length","isRegistered","dispose","clearAll","ready","tryGetSync","getSyncInstance","beginRequest","requestId","metadata","priority","add","log","removeActiveRequest","delete","getActiveRequestIds","hasActiveRequest","clear","InjectableScope","InjectableType","InjectionToken","globalRegistry","InjectableTokenMeta","Factory","scope","Singleton","token","registry","target","context","kind","Function","Error","injectableToken","create","set","Injectable","InjectableScope","scope","Transient","EventEmitter","listeners","Map","on","event","listener","has","set","Set","get","add","off","delete","size","once","args","emit","Promise","all","Array","from","map","Container","Injectable","InjectableScope","InjectableType","globalRegistry","getInjectableToken","TestBindingBuilder","container","token","toValue","value","instanceName","getServiceLocator","getInstanceIdentifier","getManager","storeCreatedHolder","Class","Singleton","toClass","target","set","TestContainer","registry","logger","injectors","undefined","bind","realToken","bindValue","bindClass","createChild","__testing__","forceSyncMode"],"sources":["../../src/internal/context/sync-local-storage.mts","../../src/internal/context/async-local-storage.mts","../../src/enums/injectable-scope.enum.mts","../../src/enums/injectable-type.enum.mts","../../src/token/injection-token.mts","../../src/token/registry.mts","../../src/symbols/injectable-token.mts","../../src/decorators/injectable.decorator.mts","../../src/errors/di-error.mts","../../src/internal/context/resolution-context.mts","../../src/utils/get-injectors.mts","../../src/utils/get-injectable-token.mts","../../src/injectors.mts","../../src/internal/lifecycle/circular-detector.mts","../../src/internal/holder/instance-holder.mts","../../src/internal/holder/base-holder-manager.mts","../../src/internal/context/request-context.mts","../../src/internal/holder/request-storage.mts","../../src/container/scoped-container.mts","../../src/internal/holder/singleton-storage.mts","../../src/internal/core/instance-resolver.mts","../../src/internal/core/instantiator.mts","../../src/internal/core/invalidator.mts","../../src/internal/lifecycle/lifecycle-event-bus.mts","../../src/internal/holder/holder-manager.mts","../../src/internal/core/token-processor.mts","../../src/internal/core/service-locator.mts","../../src/container/container.mts","../../src/decorators/factory.decorator.mts","../../src/event-emitter.mts","../../src/testing/test-container.mts","../../src/browser.mts"],"sourcesContent":["/**\n * A synchronous-only polyfill for AsyncLocalStorage.\n *\n * This provides the same API as Node's AsyncLocalStorage but only works\n * for synchronous code paths. It uses a simple stack-based approach.\n *\n * Limitations:\n * - Context does NOT propagate across async boundaries (setTimeout, promises, etc.)\n * - Only suitable for environments where DI resolution is synchronous\n *\n * This is acceptable for browser environments where:\n * 1. Constructors are typically synchronous\n * 2. Circular dependency detection mainly needs sync tracking\n */\nexport class SyncLocalStorage<T> {\n private stack: T[] = []\n\n /**\n * Runs a function within the given store context.\n * The context is only available synchronously within the function.\n */\n run<R>(store: T, fn: () => R): R {\n this.stack.push(store)\n try {\n return fn()\n } finally {\n this.stack.pop()\n }\n }\n\n /**\n * Gets the current store value, or undefined if not in a context.\n */\n getStore(): T | undefined {\n return this.stack.length > 0 ? this.stack[this.stack.length - 1] : undefined\n }\n\n /**\n * Exits the current context and runs the function without any store.\n * This matches AsyncLocalStorage.exit() behavior.\n */\n exit<R>(fn: () => R): R {\n const savedStack = this.stack\n this.stack = []\n try {\n return fn()\n } finally {\n this.stack = savedStack\n }\n }\n}\n","/**\n * Cross-platform AsyncLocalStorage wrapper.\n *\n * Provides AsyncLocalStorage on Node.js/Bun and falls back to\n * a synchronous-only polyfill in browser environments.\n */\n\nimport { SyncLocalStorage } from './sync-local-storage.mjs'\n\n/**\n * Interface matching the subset of AsyncLocalStorage API we use.\n */\nexport interface IAsyncLocalStorage<T> {\n run<R>(store: T, fn: () => R): R\n getStore(): T | undefined\n}\n\n/**\n * Detects if we're running in a Node.js-like environment with async_hooks support.\n */\nfunction hasAsyncHooksSupport(): boolean {\n // Check for Node.js\n if (\n typeof process !== 'undefined' &&\n process.versions &&\n process.versions.node\n ) {\n return true\n }\n\n // Check for Bun\n if (typeof process !== 'undefined' && process.versions && 'bun' in process.versions) {\n return true\n }\n\n // Check for Deno (also supports async_hooks via node compat)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (typeof (globalThis as any).Deno !== 'undefined') {\n return true\n }\n\n return false\n}\n\n// Cache for the AsyncLocalStorage class\nlet AsyncLocalStorageClass: (new <T>() => IAsyncLocalStorage<T>) | null = null\nlet initialized = false\nlet forceSyncMode = false\n\n/**\n * Gets the appropriate AsyncLocalStorage implementation for the current environment.\n *\n * - On Node.js/Bun/Deno: Returns the native AsyncLocalStorage\n * - On browsers: Returns SyncLocalStorage polyfill\n */\nfunction getAsyncLocalStorageClass(): new <T>() => IAsyncLocalStorage<T> {\n if (initialized) {\n return AsyncLocalStorageClass!\n }\n\n initialized = true\n\n if (!forceSyncMode && hasAsyncHooksSupport()) {\n try {\n // Dynamic require to avoid bundler issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const asyncHooks = require('node:async_hooks')\n AsyncLocalStorageClass = asyncHooks.AsyncLocalStorage\n } catch {\n // Fallback if require fails (shouldn't happen in Node/Bun)\n AsyncLocalStorageClass = SyncLocalStorage as any\n }\n } else {\n AsyncLocalStorageClass = SyncLocalStorage as any\n }\n\n return AsyncLocalStorageClass!\n}\n\n/**\n * Creates a new AsyncLocalStorage instance appropriate for the current environment.\n */\nexport function createAsyncLocalStorage<T>(): IAsyncLocalStorage<T> {\n const StorageClass = getAsyncLocalStorageClass()\n return new StorageClass<T>()\n}\n\n/**\n * Returns true if we're using the real AsyncLocalStorage (Node/Bun/Deno).\n * Returns false if we're using the sync-only polyfill (browser).\n */\nexport function isUsingNativeAsyncLocalStorage(): boolean {\n getAsyncLocalStorageClass() // Ensure initialized\n return AsyncLocalStorageClass !== (SyncLocalStorage as any)\n}\n\n/**\n * Testing utilities for forcing specific modes.\n * Only exported for testing purposes.\n */\nexport const __testing__ = {\n /**\n * Resets the initialization state and forces sync mode.\n * Call this before creating new storage instances in tests.\n */\n forceSyncMode: () => {\n initialized = false\n forceSyncMode = true\n AsyncLocalStorageClass = null\n },\n\n /**\n * Resets to default behavior (auto-detect environment).\n */\n reset: () => {\n initialized = false\n forceSyncMode = false\n AsyncLocalStorageClass = null\n },\n}\n","export enum InjectableScope {\n /**\n * Singleton scope: The instance is created once and shared across the application.\n */\n Singleton = 'Singleton',\n /**\n * Instance scope: A new instance is created for each injection.\n */\n Transient = 'Transient',\n /**\n * Request scope: The instance is created once per request and shared within that request context.\n */\n Request = 'Request',\n}\n","export enum InjectableType {\n Class = 'Class',\n Factory = 'Factory',\n}\n","import type { z, ZodObject, ZodOptional, ZodRecord } from 'zod/v4'\n\nimport type { FactoryContext } from '../internal/context/factory-context.mjs'\n\nexport type ClassType = new (...args: any[]) => any\nexport type ClassTypeWithoutArguments = new () => any\nexport type ClassTypeWithArgument<Arg> = new (arg: Arg) => any\nexport type ClassTypeWithOptionalArgument<Arg> = new (arg?: Arg) => any\n\nexport type ClassTypeWithInstance<T> = new (...args: any[]) => T\nexport type ClassTypeWithInstanceAndArgument<T, Arg> = new (arg: Arg) => T\nexport type ClassTypeWithInstanceAndOptionalArgument<T, Arg> = new (\n arg?: Arg,\n) => T\n\nexport type BaseInjectionTokenSchemaType = ZodObject | ZodRecord\n\nexport type OptionalInjectionTokenSchemaType =\n | ZodOptional<ZodObject>\n | ZodOptional<ZodRecord>\n\nexport type InjectionTokenSchemaType =\n | BaseInjectionTokenSchemaType\n | OptionalInjectionTokenSchemaType\n\nexport class InjectionToken<\n // oxlint-disable-next-line no-unused-vars\n T,\n S extends InjectionTokenSchemaType | unknown = unknown,\n // oxlint-disable-next-line no-unused-vars\n Required extends boolean = S extends ZodOptional<ZodObject>\n ? false\n : S extends ZodOptional<ZodRecord>\n ? false\n : S extends ZodObject\n ? true\n : S extends ZodRecord\n ? true\n : false,\n> {\n public id = globalThis.crypto.randomUUID()\n private formattedName: string | null = null\n\n constructor(\n public readonly name: string | symbol | ClassType,\n public readonly schema: ZodObject | undefined,\n ) {}\n\n static create<T extends ClassType>(\n name: T,\n ): InjectionToken<InstanceType<T>, undefined>\n static create<T extends ClassType, Schema extends InjectionTokenSchemaType>(\n name: T,\n schema: Schema,\n ): Schema['_def']['type'] extends 'ZodOptional'\n ? InjectionToken<InstanceType<T>, Schema, false>\n : InjectionToken<InstanceType<T>, Schema, true>\n static create<T>(name: string | symbol): InjectionToken<T, undefined>\n static create<T, Schema extends InjectionTokenSchemaType>(\n name: string | any,\n schema: Schema,\n ): InjectionToken<T, Schema>\n static create(name: string | symbol, schema?: unknown) {\n // @ts-expect-error\n return new InjectionToken(name, schema)\n }\n\n static bound<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n value: z.input<S>,\n ): BoundInjectionToken<T, S> {\n return new BoundInjectionToken(token, value)\n }\n\n static factory<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n factory: (ctx: FactoryContext) => Promise<z.input<S>>,\n ): FactoryInjectionToken<T, S> {\n return new FactoryInjectionToken(token, factory)\n }\n\n static refineType<T>(\n token: BoundInjectionToken<any, any>,\n ): BoundInjectionToken<T, any> {\n return token as BoundInjectionToken<T, any>\n }\n\n toString() {\n if (this.formattedName) {\n return this.formattedName\n }\n const { name } = this\n if (typeof name === 'function') {\n const className = name.name\n this.formattedName = `${className}(${this.id})`\n } else if (typeof name === 'symbol') {\n this.formattedName = `${name.toString()}(${this.id})`\n } else {\n this.formattedName = `${name}(${this.id})`\n }\n\n return this.formattedName\n }\n}\n\nexport class BoundInjectionToken<T, S extends InjectionTokenSchemaType> {\n public id: string\n public name: string | symbol | ClassType\n public schema: InjectionTokenSchemaType\n\n constructor(\n public readonly token: InjectionToken<T, S>,\n public readonly value: z.input<S>,\n ) {\n this.name = token.name\n this.id = token.id\n this.schema = token.schema as InjectionTokenSchemaType\n }\n\n toString() {\n return this.token.toString()\n }\n}\n\nexport class FactoryInjectionToken<T, S extends InjectionTokenSchemaType> {\n public value?: z.input<S>\n public resolved = false\n public id: string\n public name: string | symbol | ClassType\n public schema: InjectionTokenSchemaType\n\n constructor(\n public readonly token: InjectionToken<T, S>,\n public readonly factory: (ctx: FactoryContext) => Promise<z.input<S>>,\n ) {\n this.name = token.name\n this.id = token.id\n this.schema = token.schema as InjectionTokenSchemaType\n }\n\n async resolve(ctx: FactoryContext): Promise<z.input<S>> {\n if (!this.value) {\n this.value = await this.factory(ctx)\n this.resolved = true\n }\n return this.value\n }\n\n toString() {\n return this.token.toString()\n }\n}\n\nexport type AnyInjectableType =\n | ClassType\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>\n\nexport type InjectionTokenType =\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>\n","import type { ClassType, InjectionToken } from './injection-token.mjs'\n\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\n\nexport type FactoryRecord<Instance = any, Schema = any> = {\n scope: InjectableScope\n originalToken: InjectionToken<Instance, Schema>\n target: ClassType\n type: InjectableType\n}\n\nexport class Registry {\n private readonly factories = new Map<string, FactoryRecord>()\n\n constructor(private readonly parent?: Registry) {}\n\n has(token: InjectionToken<any, any>): boolean {\n if (this.factories.has(token.id)) {\n return true\n }\n if (this.parent) {\n return this.parent.has(token)\n }\n return false\n }\n\n get<Instance, Schema>(\n token: InjectionToken<Instance, Schema>,\n ): FactoryRecord<Instance, Schema> {\n const factory = this.factories.get(token.id)\n if (!factory) {\n if (this.parent) {\n return this.parent.get(token)\n }\n throw new Error(`[Registry] No factory found for ${token.toString()}`)\n }\n return factory\n }\n\n set<Instance, Schema>(\n token: InjectionToken<Instance, Schema>,\n scope: InjectableScope,\n target: ClassType,\n type: InjectableType,\n ) {\n this.factories.set(token.id, { scope, originalToken: token, target, type })\n }\n\n delete(token: InjectionToken<any, any>) {\n this.factories.delete(token.id)\n }\n}\n\nexport const globalRegistry = new Registry()\n","export const InjectableTokenMeta = Symbol.for('InjectableTokenMeta')\n","import { z } from 'zod/v4'\n\nimport type {\n BaseInjectionTokenSchemaType,\n ClassType,\n ClassTypeWithArgument,\n ClassTypeWithInstance,\n ClassTypeWithInstanceAndArgument,\n ClassTypeWithInstanceAndOptionalArgument,\n ClassTypeWithOptionalArgument,\n ClassTypeWithoutArguments,\n InjectionTokenSchemaType,\n OptionalInjectionTokenSchemaType,\n} from '../token/injection-token.mjs'\nimport type { Registry } from '../token/registry.mjs'\n\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\nimport { InjectionToken } from '../token/injection-token.mjs'\nimport { globalRegistry } from '../token/registry.mjs'\nimport { InjectableTokenMeta } from '../symbols/index.mjs'\n\nexport interface InjectableOptions {\n scope?: InjectableScope\n token?: InjectionToken<any, any>\n schema?: InjectionTokenSchemaType\n registry?: Registry\n}\n// #1 Simple constructorless class\nexport function Injectable(): <T extends ClassTypeWithoutArguments>(\n target: T,\n context?: ClassDecoratorContext,\n) => T\nexport function Injectable(options: {\n scope?: InjectableScope\n registry: Registry\n}): <T extends ClassTypeWithoutArguments>(\n target: T,\n context?: ClassDecoratorContext,\n) => T\nexport function Injectable(options: {\n scope: InjectableScope\n}): <T extends ClassTypeWithoutArguments>(\n target: T,\n context?: ClassDecoratorContext,\n) => T\n// #2 Class with schema\nexport function Injectable<Schema extends InjectionTokenSchemaType>(options: {\n scope?: InjectableScope\n schema: Schema\n registry?: Registry\n}): <T extends ClassTypeWithArgument<z.output<Schema>>>(\n target: T,\n context?: ClassDecoratorContext,\n) => T\n\n// #3 Class with typeless token and schema\nexport function Injectable<Type, Schema>(options: {\n scope?: InjectableScope\n token: InjectionToken<Type, Schema>\n registry?: Registry\n}): Schema extends BaseInjectionTokenSchemaType // #3.1 Check that schema is an object or a record\n ? Type extends undefined\n ? <T extends ClassTypeWithArgument<z.output<Schema>>>( // #3.1.1 Typeless token\n target: T,\n context?: ClassDecoratorContext,\n ) => T\n : <T extends ClassTypeWithInstanceAndArgument<Type, z.output<Schema>>>( // #3.1.2 Typed token\n target: T,\n context?: ClassDecoratorContext,\n ) => T\n : Schema extends OptionalInjectionTokenSchemaType // #3.2 Check that schema is an optional object or a record\n ? Type extends undefined\n ? <T extends ClassTypeWithOptionalArgument<z.output<Schema>>>( // #3.2.1 Typeless token\n target: T,\n context?: ClassDecoratorContext,\n ) => T\n : <\n // #3.2.2 Typed token\n T extends ClassTypeWithInstanceAndOptionalArgument<\n Type,\n z.output<Schema>\n >,\n >(\n target: T,\n context?: ClassDecoratorContext,\n ) => T\n : Schema extends undefined // #3.3 Check that schema is undefined\n ? <R extends ClassTypeWithInstance<Type>>( // #3.3.1 Token must have a type\n target: R,\n context?: ClassDecoratorContext,\n ) => R\n : never // #3.4 Cannot use a token without a type and schema\n\nexport function Injectable({\n scope = InjectableScope.Singleton,\n token,\n schema,\n registry = globalRegistry,\n}: InjectableOptions = {}) {\n return <T extends ClassType>(\n target: T,\n context?: ClassDecoratorContext,\n ): T => {\n if (\n (context && context.kind !== 'class') ||\n (target instanceof Function && !context)\n ) {\n throw new Error(\n '[ServiceLocator] @Injectable decorator can only be used on classes.',\n )\n }\n if (schema && token) {\n throw new Error(\n '[ServiceLocator] @Injectable decorator cannot have both a token and a schema',\n )\n }\n let injectableToken: InjectionToken<any, any> =\n token ?? InjectionToken.create(target, schema as InjectionTokenSchemaType)\n\n registry.set(injectableToken, scope, target, InjectableType.Class)\n\n // @ts-expect-error\n target[InjectableTokenMeta] = injectableToken\n\n return target\n }\n}\n","export enum DIErrorCode {\n FactoryNotFound = 'FactoryNotFound',\n FactoryTokenNotResolved = 'FactoryTokenNotResolved',\n InstanceNotFound = 'InstanceNotFound',\n InstanceDestroying = 'InstanceDestroying',\n CircularDependency = 'CircularDependency',\n UnknownError = 'UnknownError',\n}\n\nexport class DIError extends Error {\n public readonly context?: Record<string, unknown>\n\n constructor(\n public readonly code: DIErrorCode,\n public readonly message: string,\n context?: Record<string, unknown>,\n ) {\n super(message)\n this.context = context\n }\n\n // Static factory methods for common error types\n static factoryNotFound(name: string): DIError {\n return new DIError(\n DIErrorCode.FactoryNotFound,\n `Factory ${name} not found`,\n { name },\n )\n }\n\n static factoryTokenNotResolved(token: string | symbol | unknown): DIError {\n return new DIError(\n DIErrorCode.FactoryTokenNotResolved,\n `Factory token not resolved: ${token?.toString() ?? 'unknown'}`,\n { token },\n )\n }\n\n static instanceNotFound(name: string): DIError {\n return new DIError(\n DIErrorCode.InstanceNotFound,\n `Instance ${name} not found`,\n { name },\n )\n }\n\n static instanceDestroying(name: string): DIError {\n return new DIError(\n DIErrorCode.InstanceDestroying,\n `Instance ${name} destroying`,\n { name },\n )\n }\n\n static unknown(\n message: string | Error,\n context?: Record<string, unknown>,\n ): DIError {\n if (message instanceof Error) {\n return new DIError(DIErrorCode.UnknownError, message.message, {\n ...context,\n parent: message,\n })\n }\n return new DIError(DIErrorCode.UnknownError, message, context)\n }\n\n static circularDependency(cycle: string[]): DIError {\n const cycleStr = cycle.join(' -> ')\n return new DIError(\n DIErrorCode.CircularDependency,\n `Circular dependency detected: ${cycleStr}`,\n { cycle },\n )\n }\n}\n","import type { InstanceHolder } from '../holder/instance-holder.mjs'\n\nimport { createAsyncLocalStorage } from './async-local-storage.mjs'\n\n/**\n * Data stored in the resolution context during service instantiation.\n */\nexport interface ResolutionContextData {\n /** The holder that is currently being instantiated */\n waiterHolder: InstanceHolder\n /** Function to get a holder by name (for cycle detection) */\n getHolder: (name: string) => InstanceHolder | undefined\n}\n\n/**\n * AsyncLocalStorage for tracking the current resolution context.\n *\n * This allows tracking which service is being instantiated even across\n * async boundaries (like when inject() is called inside a constructor).\n * Essential for circular dependency detection.\n */\nexport const resolutionContext = createAsyncLocalStorage<ResolutionContextData>()\n\n/**\n * Runs a function within a resolution context.\n *\n * The context tracks which holder is currently being instantiated,\n * allowing circular dependency detection to work correctly.\n *\n * @param waiterHolder The holder being instantiated\n * @param getHolder Function to retrieve holders by name\n * @param fn The function to run within the context\n */\nexport function withResolutionContext<T>(\n waiterHolder: InstanceHolder,\n getHolder: (name: string) => InstanceHolder | undefined,\n fn: () => T,\n): T {\n return resolutionContext.run({ waiterHolder, getHolder }, fn)\n}\n\n/**\n * Gets the current resolution context, if any.\n *\n * Returns undefined if we're not inside a resolution context\n * (e.g., when resolving a top-level service that has no parent).\n */\nexport function getCurrentResolutionContext(): ResolutionContextData | undefined {\n return resolutionContext.getStore()\n}\n\n/**\n * Runs a function outside any resolution context.\n *\n * This is useful for async injections that should not participate\n * in circular dependency detection since they don't block.\n *\n * @param fn The function to run without resolution context\n */\nexport function withoutResolutionContext<T>(fn: () => T): T {\n // Run with undefined context to clear any current context\n return resolutionContext.run(undefined as any, fn)\n}\n","import type { z, ZodObject, ZodType } from 'zod/v4'\n\nimport type { FactoryContext } from '../internal/context/factory-context.mjs'\nimport type {\n BoundInjectionToken,\n ClassType,\n ClassTypeWithArgument,\n ClassTypeWithoutArguments,\n FactoryInjectionToken,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '../token/injection-token.mjs'\nimport type {\n Factorable,\n FactorableWithArgs,\n} from '../interfaces/factory.interface.mjs'\nimport type {\n InjectRequest,\n InjectState,\n Join,\n UnionToArray,\n} from './types.mjs'\n\nimport { InjectableTokenMeta } from '../symbols/index.mjs'\nimport { withoutResolutionContext } from '../internal/context/resolution-context.mjs'\n\nexport interface Injectors {\n // #1 Simple class\n asyncInject<T extends ClassTypeWithoutArguments>(\n token: T,\n ): InstanceType<T> extends Factorable<infer R>\n ? Promise<R>\n : Promise<InstanceType<T>>\n asyncInject<Args, T extends ClassTypeWithArgument<Args>>(\n token: T,\n args: Args,\n ): Promise<InstanceType<T>>\n asyncInject<\n Schema extends InjectionTokenSchemaType,\n R,\n T extends FactorableWithArgs<R, Schema>,\n >(\n token: T,\n args: z.input<Schema>,\n ): Promise<R>\n\n // #2 Token with required Schema\n asyncInject<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n ): Promise<T>\n // #3 Token with optional Schema\n asyncInject<T, S extends InjectionTokenSchemaType, R extends boolean>(\n token: InjectionToken<T, S, R>,\n ): R extends false\n ? Promise<T>\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<\n UnionToArray<keyof Type>,\n ', '\n >}`\n : 'Error: Your token requires args'\n // #4 Token with no Schema\n asyncInject<T>(token: InjectionToken<T, undefined>): Promise<T>\n asyncInject<T>(token: BoundInjectionToken<T, any>): Promise<T>\n asyncInject<T>(token: FactoryInjectionToken<T, any>): Promise<T>\n\n inject<T extends ClassTypeWithoutArguments>(\n token: T,\n ): InstanceType<T> extends Factorable<infer R> ? R : InstanceType<T>\n inject<Args, T extends ClassTypeWithArgument<Args>>(\n token: T,\n args: Args,\n ): InstanceType<T>\n inject<\n Schema extends InjectionTokenSchemaType,\n R,\n T extends FactorableWithArgs<R, Schema>,\n >(\n token: T,\n args: z.input<Schema>,\n ): R\n\n inject<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n ): T\n // #3 Token with optional Schema\n inject<T, S extends InjectionTokenSchemaType, R extends boolean>(\n token: InjectionToken<T, S, R>,\n ): R extends false\n ? T\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<\n UnionToArray<keyof Type>,\n ', '\n >}`\n : 'Error: Your token requires args'\n inject<T>(token: InjectionToken<T, undefined>): T\n inject<T>(token: BoundInjectionToken<T, any>): T\n inject<T>(token: FactoryInjectionToken<T, any>): T\n\n /**\n * Optional injection that returns null if the service fails to initialize\n * or is not available. This is useful when you want to inject a service\n * that may not be configured or may fail gracefully.\n *\n * @example\n * ```ts\n * class MyService {\n * constructor() {\n * const optionalService = optional(OptionalServiceToken)\n * // optionalService will be null if initialization fails\n * if (optionalService) {\n * optionalService.doSomething()\n * }\n * }\n * }\n * ```\n */\n optional<T extends ClassType>(\n token: T,\n ): (InstanceType<T> extends Factorable<infer R> ? R : InstanceType<T>) | null\n optional<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n ): T | null\n optional<T, S extends InjectionTokenSchemaType, R extends boolean>(\n token: InjectionToken<T, S, R>,\n ): R extends false\n ? T | null\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<\n UnionToArray<keyof Type>,\n ', '\n >}`\n : 'Error: Your token requires args'\n optional<T>(token: InjectionToken<T, undefined>): T | null\n optional<T>(token: BoundInjectionToken<T, any>): T | null\n optional<T>(token: FactoryInjectionToken<T, any>): T | null\n\n wrapSyncInit(\n cb: () => any,\n ): (injectState?: InjectState) => [any, Promise<any>[], InjectState]\n\n provideFactoryContext(context: FactoryContext | null): FactoryContext | null\n}\n\nexport function getInjectors() {\n let currentFactoryContext: FactoryContext | null = null\n\n function provideFactoryContext(\n context: FactoryContext,\n ): FactoryContext | null {\n const original = currentFactoryContext\n currentFactoryContext = context\n return original\n }\n function getFactoryContext(): FactoryContext {\n if (!currentFactoryContext) {\n throw new Error(\n '[Injector] Trying to access injection context outside of a injectable context',\n )\n }\n return currentFactoryContext\n }\n\n let promiseCollector: null | ((promise: Promise<any>) => void) = null\n let injectState: InjectState | null = null\n\n function getRequest(\n token: InjectionToken<any>,\n args?: unknown,\n skipCycleTracking = false,\n ) {\n if (!injectState) {\n throw new Error(\n '[Injector] Trying to make a request outside of a injectable context',\n )\n }\n if (injectState.isFrozen) {\n const idx = injectState.currentIndex++\n const request = injectState.requests[idx]\n if (request.token !== token) {\n throw new Error(\n `[Injector] Wrong token order. Expected ${request.token.toString()} but got ${token.toString()}`,\n )\n }\n return request\n }\n let result: any = null\n let error: Error | null = null\n\n // For async inject, we run outside the resolution context to skip cycle tracking.\n // This is because asyncInject returns a promise that doesn't block the constructor,\n // so it cannot cause a deadlock even with circular dependencies.\n const doInject = () =>\n getFactoryContext()\n .inject(token as any, args as any)\n .then((r) => {\n result = r\n return r\n })\n .catch((e) => {\n // We don't throw here because we have a mechanism to handle errors\n error = e\n })\n\n const promise = skipCycleTracking\n ? withoutResolutionContext(doInject)\n : doInject()\n\n const request: InjectRequest = {\n token,\n promise,\n get result() {\n return result\n },\n get error() {\n return error\n },\n }\n injectState.requests.push(request)\n injectState.currentIndex++\n\n return request\n }\n\n function asyncInject(\n token:\n | ClassType\n | InjectionToken<any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args?: unknown,\n ) {\n if (!injectState) {\n throw new Error(\n '[Injector] Trying to access inject outside of a injectable context',\n )\n }\n // @ts-expect-error In case we have a class\n const realToken = token[InjectableTokenMeta] ?? token\n // Pass skipCycleTracking=true because asyncInject returns a promise that doesn't\n // block the constructor, so it cannot cause a deadlock even with circular dependencies.\n const request = getRequest(realToken, args, true)\n return request.promise.then((result) => {\n if (request.error) {\n // We throw here because we want to fail the asyncInject call if the dependency fails to initialize\n throw request.error\n }\n return result\n })\n }\n\n function wrapSyncInit(cb: () => any) {\n return (previousState?: InjectState) => {\n const promises: Promise<any>[] = []\n const originalPromiseCollector = promiseCollector\n const originalInjectState = injectState\n injectState = previousState\n ? {\n ...previousState,\n currentIndex: 0,\n }\n : {\n currentIndex: 0,\n isFrozen: false,\n requests: [],\n }\n promiseCollector = (promise) => {\n promises.push(promise)\n }\n const result = cb()\n promiseCollector = originalPromiseCollector\n const newInjectState = {\n ...injectState,\n isFrozen: true,\n }\n injectState = originalInjectState\n return [result, promises, newInjectState]\n }\n }\n\n function inject<\n T,\n Token extends\n | InjectionToken<T>\n | BoundInjectionToken<T, any>\n | FactoryInjectionToken<T, any>,\n S extends ZodObject | unknown = Token['schema'],\n >(token: Token, args?: S extends ZodObject ? z.input<S> : never): T {\n // @ts-expect-error In case we have a class\n const realToken = token[InjectableTokenMeta] ?? token\n\n if (!injectState) {\n throw new Error(\n '[Injector] Trying to access inject outside of a injectable context',\n )\n }\n\n const instance = getFactoryContext().container.tryGetSync(\n realToken,\n args,\n )\n if (!instance) {\n const request = getRequest(realToken, args)\n if (request.error) {\n throw request.error\n } else if (request.result) {\n return request.result\n }\n if (promiseCollector) {\n promiseCollector(request.promise)\n }\n // Return a dynamic proxy that looks up the instance when accessed\n return new Proxy(\n {},\n {\n get() {\n throw new Error(\n `[Injector] Trying to access ${realToken.toString()} before it's initialized, please move the code to a onServiceInit method`,\n )\n },\n },\n ) as unknown as T\n }\n return instance as unknown as T\n }\n\n function optional<\n T,\n Token extends\n | InjectionToken<T>\n | BoundInjectionToken<T, any>\n | FactoryInjectionToken<T, any>,\n S extends ZodObject | unknown = Token['schema'],\n >(token: Token, args?: S extends ZodObject ? z.input<S> : never): T | null {\n try {\n return inject(token, args)\n } catch {\n // If injection fails, return null instead of throwing\n return null\n }\n }\n\n const injectors: Injectors = {\n asyncInject,\n inject,\n optional,\n wrapSyncInit,\n provideFactoryContext,\n } as Injectors\n\n return injectors\n}\n","import type { ClassType, InjectionToken } from '../token/injection-token.mjs'\n\nimport { InjectableTokenMeta } from '../symbols/index.mjs'\n\nexport function getInjectableToken<R>(\n target: ClassType,\n): R extends { create(...args: any[]): infer V }\n ? InjectionToken<V>\n : InjectionToken<R> {\n // @ts-expect-error We inject the token into the class itself\n const token = target[InjectableTokenMeta] as InjectionToken<any, any>\n if (!token) {\n throw new Error(\n `[ServiceLocator] Class ${target.name} is not decorated with @Injectable.`,\n )\n }\n // @ts-expect-error We detect factory or class\n return token\n}\n","import type { Injectors } from './utils/index.mjs'\n\nimport { getInjectors } from './utils/index.mjs'\n\nexport const defaultInjectors = getInjectors()\n\nexport const asyncInject: Injectors['asyncInject'] =\n defaultInjectors.asyncInject\n\nexport const inject: Injectors['inject'] = defaultInjectors.inject\n\nexport const optional: Injectors['optional'] = defaultInjectors.optional\n\nexport const wrapSyncInit: Injectors['wrapSyncInit'] =\n defaultInjectors.wrapSyncInit\n\nexport const provideFactoryContext: Injectors['provideFactoryContext'] =\n defaultInjectors.provideFactoryContext\n","import type { InstanceHolder } from '../holder/instance-holder.mjs'\n\n/**\n * Detects circular dependencies by analyzing the waitingFor relationships\n * between service holders.\n *\n * Uses BFS to traverse the waitingFor graph starting from a target holder\n * and checks if following the chain leads back to the waiter, indicating a circular dependency.\n */\nexport class CircularDetector {\n /**\n * Detects if waiting for `targetName` from `waiterName` would create a cycle.\n *\n * This works by checking if `targetName` (or any holder in its waitingFor chain)\n * is currently waiting for `waiterName`. If so, waiting would create a deadlock.\n *\n * @param waiterName The name of the holder that wants to wait\n * @param targetName The name of the holder being waited on\n * @param getHolder Function to retrieve a holder by name\n * @returns The cycle path if a cycle is detected, null otherwise\n */\n static detectCycle(\n waiterName: string,\n targetName: string,\n getHolder: (name: string) => InstanceHolder | undefined,\n ): string[] | null {\n // Use BFS to find if there's a path from targetName back to waiterName\n const visited = new Set<string>()\n const queue: Array<{ name: string; path: string[] }> = [\n { name: targetName, path: [waiterName, targetName] },\n ]\n\n while (queue.length > 0) {\n const { name: currentName, path } = queue.shift()!\n\n // If we've reached back to the waiter, we have a cycle\n if (currentName === waiterName) {\n return path\n }\n\n // Skip if already visited\n if (visited.has(currentName)) {\n continue\n }\n visited.add(currentName)\n\n // Get the holder and check what it's waiting for\n const holder = getHolder(currentName)\n if (!holder) {\n continue\n }\n\n // Add all services this holder is waiting for to the queue\n for (const waitingForName of holder.waitingFor) {\n if (!visited.has(waitingForName)) {\n queue.push({\n name: waitingForName,\n path: [...path, waitingForName],\n })\n }\n }\n }\n\n // No path found from target back to waiter, no cycle\n return null\n }\n\n /**\n * Formats a cycle path into a human-readable string.\n *\n * @param cycle The cycle path (array of service names)\n * @returns Formatted string like \"ServiceA -> ServiceB -> ServiceA\"\n */\n static formatCycle(cycle: string[]): string {\n return cycle.join(' -> ')\n }\n}\n","import type { InjectableScope, InjectableType } from '../../enums/index.mjs'\n\n/**\n * Represents the lifecycle status of an instance holder.\n */\nexport enum InstanceStatus {\n /** Instance has been successfully created and is ready for use */\n Created = 'created',\n /** Instance is currently being created (async initialization in progress) */\n Creating = 'creating',\n /** Instance is being destroyed (cleanup in progress) */\n Destroying = 'destroying',\n /** Instance creation failed with an error */\n Error = 'error',\n}\n\n/** Callback function for instance effects */\nexport type InstanceEffect = () => void\n\n/** Callback function for instance destruction listeners */\nexport type InstanceDestroyListener = () => void | Promise<void>\n\n/**\n * Instance holder in the Creating state.\n * The instance is null while creation is in progress.\n */\nexport interface InstanceHolderCreating<Instance> {\n status: InstanceStatus.Creating\n name: string\n instance: null\n creationPromise: Promise<[undefined, Instance]> | null\n destroyPromise: null\n type: InjectableType\n scope: InjectableScope\n deps: Set<string>\n destroyListeners: InstanceDestroyListener[]\n createdAt: number\n /** Tracks which services this holder is currently waiting for (for circular dependency detection) */\n waitingFor: Set<string>\n}\n\n/**\n * Instance holder in the Created state.\n * The instance is available and ready for use.\n */\nexport interface InstanceHolderCreated<Instance> {\n status: InstanceStatus.Created\n name: string\n instance: Instance\n creationPromise: null\n destroyPromise: null\n type: InjectableType\n scope: InjectableScope\n deps: Set<string>\n destroyListeners: InstanceDestroyListener[]\n createdAt: number\n /** Tracks which services this holder is currently waiting for (for circular dependency detection) */\n waitingFor: Set<string>\n}\n\n/**\n * Instance holder in the Destroying state.\n * The instance may still be available but is being cleaned up.\n */\nexport interface InstanceHolderDestroying<Instance> {\n status: InstanceStatus.Destroying\n name: string\n instance: Instance | null\n creationPromise: null\n destroyPromise: Promise<void>\n type: InjectableType\n scope: InjectableScope\n deps: Set<string>\n destroyListeners: InstanceDestroyListener[]\n createdAt: number\n /** Tracks which services this holder is currently waiting for (for circular dependency detection) */\n waitingFor: Set<string>\n}\n\n/**\n * Instance holder in the Error state.\n * The instance field contains the error that occurred during creation.\n */\nexport interface InstanceHolderError {\n status: InstanceStatus.Error\n name: string\n instance: Error\n creationPromise: null\n destroyPromise: null\n type: InjectableType\n scope: InjectableScope\n deps: Set<string>\n destroyListeners: InstanceDestroyListener[]\n createdAt: number\n /** Tracks which services this holder is currently waiting for (for circular dependency detection) */\n waitingFor: Set<string>\n}\n\n/**\n * Holds the state of a service instance throughout its lifecycle.\n *\n * Tracks creation/destruction promises, dependency relationships,\n * destroy listeners, and current status (Creating, Created, Destroying, Error).\n */\nexport type InstanceHolder<Instance = unknown> =\n | InstanceHolderCreating<Instance>\n | InstanceHolderCreated<Instance>\n | InstanceHolderDestroying<Instance>\n | InstanceHolderError\n","import type { InstanceHolder } from './instance-holder.mjs'\n\nimport { InjectableScope, InjectableType } from '../../enums/index.mjs'\nimport { DIError } from '../../errors/index.mjs'\nimport { CircularDetector } from '../lifecycle/circular-detector.mjs'\nimport { InstanceStatus } from './instance-holder.mjs'\n\n/**\n * Result type for waitForHolderReady.\n * Returns either [undefined, holder] on success or [error] on failure.\n */\nexport type HolderReadyResult<T> = [undefined, InstanceHolder<T>] | [DIError]\n\n/**\n * Abstract base class providing common functionality for managing InstanceHolder objects.\n *\n * Provides shared patterns for holder storage, creation, and lifecycle management\n * used by both singleton (HolderManager) and request-scoped (RequestContext) managers.\n */\nexport abstract class BaseHolderManager {\n protected readonly _holders: Map<string, InstanceHolder>\n\n constructor(protected readonly logger: Console | null = null) {\n this._holders = new Map()\n }\n\n /**\n * Protected getter for accessing the holders map from subclasses.\n */\n protected get holders(): Map<string, InstanceHolder> {\n return this._holders\n }\n\n /**\n * Abstract method to get a holder by name. Each implementation defines its own return type\n * based on their specific error handling and validation needs.\n */\n abstract get(name: string): any\n\n /**\n * Abstract method to set a holder by name. Each implementation may have different validation logic.\n */\n abstract set(name: string, holder: InstanceHolder): void\n\n /**\n * Abstract method to check if a holder exists. Each implementation may have different validation logic.\n */\n abstract has(name: string): any\n\n /**\n * Deletes a holder by name.\n * @param name The name of the holder to delete\n * @returns true if the holder was deleted, false if it didn't exist\n */\n delete(name: string): boolean {\n return this._holders.delete(name)\n }\n\n /**\n * Filters holders based on a predicate function.\n * @param predicate Function to test each holder\n * @returns A new Map containing only the holders that match the predicate\n */\n filter(\n predicate: (value: InstanceHolder<any>, key: string) => boolean,\n ): Map<string, InstanceHolder> {\n return new Map(\n [...this._holders].filter(([key, value]) => predicate(value, key)),\n )\n }\n\n /**\n * Clears all holders from this manager.\n */\n clear(): void {\n this._holders.clear()\n }\n\n /**\n * Gets the number of holders currently managed.\n */\n size(): number {\n return this._holders.size\n }\n\n /**\n * Creates a new holder with Creating status and a deferred creation promise.\n * This is useful for creating placeholder holders that can be fulfilled later.\n * @param name The name of the instance\n * @param type The injectable type\n * @param scope The injectable scope\n * @param deps Optional set of dependencies\n * @returns A tuple containing the deferred promise and the holder\n */\n createCreatingHolder<Instance>(\n name: string,\n type: InjectableType,\n scope: InjectableScope,\n deps: Set<string> = new Set(),\n ): [\n ReturnType<typeof Promise.withResolvers<[undefined, Instance]>>,\n InstanceHolder<Instance>,\n ] {\n const deferred = Promise.withResolvers<[undefined, Instance]>()\n\n const holder: InstanceHolder<Instance> = {\n status: InstanceStatus.Creating,\n name,\n instance: null,\n creationPromise: deferred.promise,\n destroyPromise: null,\n type,\n scope,\n deps,\n destroyListeners: [],\n createdAt: Date.now(),\n waitingFor: new Set(),\n }\n\n return [deferred, holder]\n }\n\n /**\n * Creates a new holder with Created status and an actual instance.\n * This is useful for creating holders that already have their instance ready.\n * @param name The name of the instance\n * @param instance The actual instance to store\n * @param type The injectable type\n * @param scope The injectable scope\n * @param deps Optional set of dependencies\n * @returns The created holder\n */\n protected createCreatedHolder<Instance>(\n name: string,\n instance: Instance,\n type: InjectableType,\n scope: InjectableScope,\n deps: Set<string> = new Set(),\n ): InstanceHolder<Instance> {\n const holder: InstanceHolder<Instance> = {\n status: InstanceStatus.Created,\n name,\n instance,\n creationPromise: null,\n destroyPromise: null,\n type,\n scope,\n deps,\n destroyListeners: [],\n createdAt: Date.now(),\n waitingFor: new Set(),\n }\n\n return holder\n }\n\n /**\n * Gets all holder names currently managed.\n */\n getAllNames(): string[] {\n return Array.from(this._holders.keys())\n }\n\n /**\n * Gets all holders currently managed.\n */\n getAllHolders(): InstanceHolder[] {\n return Array.from(this._holders.values())\n }\n\n /**\n * Checks if this manager has any holders.\n */\n isEmpty(): boolean {\n return this._holders.size === 0\n }\n\n /**\n * Waits for a holder to be ready and returns the appropriate result.\n * This is a shared utility used by both singleton and request-scoped resolution.\n *\n * @param holder The holder to wait for\n * @param waiterHolder Optional holder that is doing the waiting (for circular dependency detection)\n * @param getHolder Optional function to retrieve holders by name (required if waiterHolder is provided)\n * @returns A promise that resolves with [undefined, holder] on success or [DIError] on failure\n */\n static async waitForHolderReady<T>(\n holder: InstanceHolder<T>,\n waiterHolder?: InstanceHolder,\n getHolder?: (name: string) => InstanceHolder | undefined,\n ): Promise<HolderReadyResult<T>> {\n switch (holder.status) {\n case InstanceStatus.Creating: {\n // Check for circular dependency before waiting\n if (waiterHolder && getHolder) {\n const cycle = CircularDetector.detectCycle(\n waiterHolder.name,\n holder.name,\n getHolder,\n )\n if (cycle) {\n return [DIError.circularDependency(cycle)]\n }\n\n // Track the waiting relationship\n waiterHolder.waitingFor.add(holder.name)\n }\n\n try {\n await holder.creationPromise\n } finally {\n // Clean up the waiting relationship\n if (waiterHolder) {\n waiterHolder.waitingFor.delete(holder.name)\n }\n }\n\n return BaseHolderManager.waitForHolderReady(\n holder,\n waiterHolder,\n getHolder,\n )\n }\n\n case InstanceStatus.Destroying:\n return [DIError.instanceDestroying(holder.name)]\n\n case InstanceStatus.Error:\n return [holder.instance as unknown as DIError]\n\n case InstanceStatus.Created:\n return [undefined, holder]\n\n default:\n return [DIError.instanceNotFound('unknown')]\n }\n }\n}\n","import type { InstanceHolder } from '../holder/instance-holder.mjs'\n\nimport { BaseHolderManager } from '../holder/base-holder-manager.mjs'\nimport { InjectableScope, InjectableType } from '../../enums/index.mjs'\nimport { InjectionToken } from '../../token/injection-token.mjs'\n\n/**\n * Interface for request context that manages pre-prepared instances for a specific request.\n *\n * Provides isolated storage for request-scoped services, enabling efficient\n * instantiation and cleanup within the lifecycle of a single request.\n */\nexport interface RequestContext {\n /**\n * Unique identifier for this request context.\n */\n readonly requestId: string\n\n /**\n * Instance holders for request-scoped services.\n */\n readonly holders: Map<string, InstanceHolder>\n\n /**\n * Priority for resolution in FactoryContext.inject method.\n * Higher values take precedence.\n */\n readonly priority: number\n\n /**\n * Request-specific metadata that can be used during instantiation.\n */\n readonly metadata: Map<string, any>\n\n /**\n * Timestamp when this context was created.\n */\n readonly createdAt: number\n\n /**\n * Adds a pre-prepared instance to this context.\n */\n addInstance(\n instanceName: string,\n instance: any,\n holder: InstanceHolder,\n ): void\n\n /**\n * Adds a pre-prepared instance to this context.\n */\n addInstance(token: InjectionToken<any, undefined>, instance: any): void\n\n /**\n * Gets an instance holder from this context.\n */\n get(instanceName: string): InstanceHolder | undefined\n\n /**\n * Sets an instance holder by name.\n */\n set(instanceName: string, holder: InstanceHolder): void\n\n /**\n * Checks if this context has a pre-prepared instance.\n */\n has(instanceName: string): boolean\n\n /**\n * Clears all instances and holders from this context.\n */\n clear(): void\n\n /**\n * Gets metadata value by key.\n */\n getMetadata(key: string): any | undefined\n\n /**\n * Sets metadata value by key.\n */\n setMetadata(key: string, value: any): void\n\n // Methods inherited from BaseHolderManager\n /**\n * Filters holders based on a predicate function.\n */\n filter(\n predicate: (\n value: InstanceHolder<any>,\n key: string,\n ) => boolean,\n ): Map<string, InstanceHolder>\n\n /**\n * Deletes a holder by name.\n */\n delete(name: string): boolean\n\n /**\n * Gets the number of holders currently managed.\n */\n size(): number\n\n /**\n * Checks if this manager has any holders.\n */\n isEmpty(): boolean\n}\n\n/** @deprecated Use RequestContext instead */\nexport type RequestContextHolder = RequestContext\n\n/**\n * Default implementation of RequestContext.\n *\n * Extends BaseHolderManager to provide holder management functionality\n * with request-specific metadata and lifecycle support.\n */\nexport class DefaultRequestContext\n extends BaseHolderManager\n implements RequestContext\n{\n public readonly metadata = new Map<string, any>()\n public readonly createdAt = Date.now()\n\n constructor(\n public readonly requestId: string,\n public readonly priority: number = 100,\n initialMetadata?: Record<string, any>,\n ) {\n super(null) // RequestContext doesn't need logging\n if (initialMetadata) {\n Object.entries(initialMetadata).forEach(([key, value]) => {\n this.metadata.set(key, value)\n })\n }\n }\n\n /**\n * Public getter for holders to maintain interface compatibility.\n */\n get holders(): Map<string, InstanceHolder> {\n return this._holders\n }\n\n /**\n * Gets a holder by name. For RequestContext, this is a simple lookup.\n */\n get(name: string): InstanceHolder | undefined {\n return this._holders.get(name)\n }\n\n /**\n * Sets a holder by name.\n */\n set(name: string, holder: InstanceHolder): void {\n this._holders.set(name, holder)\n }\n\n /**\n * Checks if a holder exists by name.\n */\n has(name: string): boolean {\n return this._holders.has(name)\n }\n\n addInstance(\n instanceName: string | InjectionToken<any, undefined>,\n instance: any,\n holder?: InstanceHolder,\n ): void {\n if (instanceName instanceof InjectionToken) {\n const name = instanceName.toString()\n const createdHolder = this.createCreatedHolder(\n name,\n instance,\n InjectableType.Class,\n InjectableScope.Singleton,\n new Set(),\n )\n this._holders.set(name, createdHolder)\n } else {\n if (!holder) {\n throw new Error('Holder is required when adding an instance by name')\n }\n this._holders.set(instanceName, holder)\n }\n }\n\n clear(): void {\n super.clear() // Use the base class clear method for holders\n this.metadata.clear()\n }\n\n getMetadata(key: string): any | undefined {\n return this.metadata.get(key)\n }\n\n setMetadata(key: string, value: any): void {\n this.metadata.set(key, value)\n }\n}\n\n/**\n * Creates a new request context with the given parameters.\n */\nexport function createRequestContext(\n requestId: string,\n priority: number = 100,\n initialMetadata?: Record<string, any>,\n): RequestContext {\n return new DefaultRequestContext(requestId, priority, initialMetadata)\n}\n","import type { RequestContext } from '../context/request-context.mjs'\nimport type { BaseHolderManager } from './base-holder-manager.mjs'\nimport type {\n HolderGetResult,\n IHolderStorage,\n} from './holder-storage.interface.mjs'\nimport type { InstanceHolder } from './instance-holder.mjs'\n\nimport { InjectableScope, InjectableType } from '../../enums/index.mjs'\nimport { DIError } from '../../errors/index.mjs'\nimport { InstanceStatus } from './instance-holder.mjs'\n\n/**\n * Storage implementation for Request-scoped services.\n *\n * Wraps a RequestContext instance from a ScopedContainer and provides\n * the IHolderStorage interface. This allows the InstanceResolver to work\n * with request-scoped storage using the same interface as singleton storage.\n */\nexport class RequestStorage implements IHolderStorage {\n readonly scope = InjectableScope.Request\n\n constructor(\n private readonly contextHolder: RequestContext,\n private readonly holderManager: BaseHolderManager,\n ) {}\n\n get<T = unknown>(instanceName: string): HolderGetResult<T> {\n const holder = this.contextHolder.get(instanceName)\n\n if (!holder) {\n return null\n }\n\n // Check holder status for error states\n switch (holder.status) {\n case InstanceStatus.Destroying:\n return [\n DIError.instanceDestroying(instanceName),\n holder as InstanceHolder<T>,\n ]\n\n case InstanceStatus.Error:\n return [\n holder.instance as unknown as DIError,\n holder as InstanceHolder<T>,\n ]\n\n case InstanceStatus.Creating:\n case InstanceStatus.Created:\n return [undefined, holder as InstanceHolder<T>]\n\n default:\n return null\n }\n }\n\n set(instanceName: string, holder: InstanceHolder): void {\n this.contextHolder.set(instanceName, holder)\n }\n\n delete(instanceName: string): boolean {\n return this.contextHolder.delete(instanceName)\n }\n\n createHolder<T>(\n instanceName: string,\n type: InjectableType,\n deps: Set<string>,\n ): [\n ReturnType<typeof Promise.withResolvers<[undefined, T]>>,\n InstanceHolder<T>,\n ] {\n // Use the holderManager's createCreatingHolder method\n // which is inherited from BaseHolderManager\n return this.holderManager.createCreatingHolder<T>(\n instanceName,\n type,\n this.scope,\n deps,\n )\n }\n\n handles(scope: InjectableScope): boolean {\n return scope === InjectableScope.Request\n }\n\n // ============================================================================\n // ITERATION AND QUERY\n // ============================================================================\n\n getAllNames(): string[] {\n const names: string[] = []\n for (const [name] of this.contextHolder.holders) {\n names.push(name)\n }\n return names\n }\n\n forEach(callback: (name: string, holder: InstanceHolder) => void): void {\n for (const [name, holder] of this.contextHolder.holders) {\n callback(name, holder)\n }\n }\n\n findByInstance(instance: unknown): InstanceHolder | null {\n for (const holder of this.contextHolder.holders.values()) {\n if (holder.instance === instance) {\n return holder\n }\n }\n return null\n }\n\n findDependents(instanceName: string): string[] {\n const dependents: string[] = []\n\n // Check request-scoped holders\n for (const [name, holder] of this.contextHolder.holders) {\n if (holder.deps.has(instanceName)) {\n dependents.push(name)\n }\n }\n\n // Also check singleton holders - a singleton may depend on this request-scoped service\n for (const [name, holder] of this.holderManager.filter(() => true)) {\n if (holder.deps.has(instanceName)) {\n dependents.push(name)\n }\n }\n\n return dependents\n }\n}\n","import type { z, ZodType } from 'zod/v4'\n\nimport type { Container } from './container.mjs'\nimport type {\n BoundInjectionToken,\n ClassType,\n ClassTypeWithArgument,\n FactoryInjectionToken,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '../token/injection-token.mjs'\nimport type { IContainer } from '../interfaces/container.interface.mjs'\nimport type { IHolderStorage } from '../internal/holder/holder-storage.interface.mjs'\nimport type { Factorable } from '../interfaces/factory.interface.mjs'\nimport type { Registry } from '../token/registry.mjs'\nimport type { RequestContext } from '../internal/context/request-context.mjs'\nimport type { InstanceHolder } from '../internal/holder/instance-holder.mjs'\nimport type { Join, UnionToArray } from '../utils/types.mjs'\n\nimport { BaseHolderManager } from '../internal/holder/base-holder-manager.mjs'\nimport { InjectableScope } from '../enums/index.mjs'\nimport { DIError } from '../errors/index.mjs'\nimport { DefaultRequestContext } from '../internal/context/request-context.mjs'\nimport { RequestStorage } from '../internal/holder/request-storage.mjs'\nimport { InstanceStatus } from '../internal/holder/instance-holder.mjs'\n\n/**\n * Request-scoped dependency injection container.\n *\n * Wraps a parent Container and provides isolated request-scoped instances\n * while delegating singleton and transient resolution to the parent.\n * This design eliminates race conditions that can occur with async operations\n * when multiple requests are processed concurrently.\n */\nexport class ScopedContainer implements IContainer {\n private readonly requestContextHolder: RequestContext\n private readonly holderStorage: IHolderStorage\n private disposed = false\n\n constructor(\n private readonly parent: Container,\n private readonly registry: Registry,\n public readonly requestId: string,\n metadata?: Record<string, any>,\n priority: number = 100,\n ) {\n this.requestContextHolder = new DefaultRequestContext(\n requestId,\n priority,\n metadata,\n )\n // Create storage once and reuse for all resolutions\n this.holderStorage = new RequestStorage(\n this.requestContextHolder,\n this.parent.getServiceLocator().getManager(),\n )\n }\n\n /**\n * Gets the request context holder for this scoped container.\n */\n getRequestContextHolder(): RequestContext {\n return this.requestContextHolder\n }\n\n /**\n * Gets the holder storage for this scoped container.\n * Used by InstanceResolver for request-scoped resolution.\n */\n getHolderStorage(): IHolderStorage {\n return this.holderStorage\n }\n\n /**\n * Gets the request ID for this scoped container.\n */\n getRequestId(): string {\n return this.requestId\n }\n\n /**\n * Gets the parent container.\n */\n getParent(): Container {\n return this.parent\n }\n\n /**\n * Gets metadata from the request context.\n */\n getMetadata(key: string): any | undefined {\n return this.requestContextHolder.getMetadata(key)\n }\n\n /**\n * Sets metadata on the request context.\n */\n setMetadata(key: string, value: any): void {\n this.requestContextHolder.setMetadata(key, value)\n }\n\n /**\n * Adds a pre-prepared instance to the request context.\n */\n addInstance(token: InjectionToken<any, undefined>, instance: any): void {\n this.requestContextHolder.addInstance(token, instance)\n }\n\n /**\n * Gets an instance from the container.\n * Request-scoped services are resolved from this container's context.\n * All other services are delegated to the parent container.\n */\n // #1 Simple class\n get<T extends ClassType>(\n token: T,\n ): InstanceType<T> extends Factorable<infer R>\n ? Promise<R>\n : Promise<InstanceType<T>>\n // #1.1 Simple class with args\n get<T extends ClassTypeWithArgument<R>, R>(\n token: T,\n args: R,\n ): Promise<InstanceType<T>>\n // #2 Token with required Schema\n get<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n ): Promise<T>\n // #3 Token with optional Schema\n get<T, S extends InjectionTokenSchemaType, R extends boolean>(\n token: InjectionToken<T, S, R>,\n ): R extends false\n ? Promise<T>\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<\n UnionToArray<keyof Type>,\n ', '\n >}`\n : 'Error: Your token requires args'\n // #4 Token with no Schema\n get<T>(token: InjectionToken<T, undefined>): Promise<T>\n get<T>(token: BoundInjectionToken<T, any>): Promise<T>\n get<T>(token: FactoryInjectionToken<T, any>): Promise<T>\n\n async get(\n token:\n | ClassType\n | InjectionToken<any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args?: unknown,\n ): Promise<any> {\n if (this.disposed) {\n throw DIError.unknown(\n `ScopedContainer for request ${this.requestId} has been disposed`,\n )\n }\n\n // Get the actual injection token using TokenProcessor for consistency\n const tokenProcessor = this.parent.getServiceLocator().getTokenProcessor()\n const actualToken = tokenProcessor.normalizeToken(token)\n\n // Check if this is a request-scoped service\n if (this.isRequestScoped(actualToken)) {\n return this.resolveRequestScoped(actualToken, args)\n }\n\n // Delegate to parent for singleton/transient services\n // Pass this ScopedContainer so nested inject() calls work correctly\n return this.parent.getWithContext(token, args, this)\n }\n\n /**\n * Invalidates a service and its dependencies.\n * For request-scoped services, invalidation is handled within this context.\n */\n async invalidate(service: unknown): Promise<void> {\n // Check if the service is in our request context\n const holder = this.holderStorage.findByInstance(service)\n if (holder) {\n // Use the shared Invalidator with our request-scoped storage\n await this.parent\n .getServiceLocator()\n .getInvalidator()\n .invalidateWithStorage(holder.name, this.holderStorage, 1, {\n emitEvents: false, // Request-scoped services don't emit global events\n })\n return\n }\n\n // Delegate to parent for singleton services\n await this.parent.invalidate(service)\n }\n\n /**\n * Checks if a service is registered.\n */\n isRegistered(token: any): boolean {\n return this.parent.isRegistered(token)\n }\n\n /**\n * Disposes this scoped container and cleans up all request-scoped instances.\n * This is an alias for endRequest() for IContainer compatibility.\n */\n async dispose(): Promise<void> {\n await this.endRequest()\n }\n\n /**\n * Ends the request and cleans up all request-scoped instances.\n * Uses the invalidation system to properly cascade to dependent singletons.\n */\n async endRequest(): Promise<void> {\n if (this.disposed) {\n return\n }\n\n this.disposed = true\n\n // Use clearAllWithStorage to properly invalidate all request-scoped services\n // This will cascade invalidation to singletons that depend on request-scoped services\n await this.parent\n .getServiceLocator()\n .getInvalidator()\n .clearAllWithStorage(this.holderStorage, {\n waitForSettlement: true,\n maxRounds: 10,\n })\n\n // Clear the context (any remaining holders that weren't invalidated)\n this.requestContextHolder.clear()\n\n // Remove from parent's active requests\n this.parent.removeActiveRequest(this.requestId)\n }\n\n /**\n * Waits for all pending operations to complete.\n */\n async ready(): Promise<void> {\n await this.parent.ready()\n }\n\n /**\n * @internal\n * Attempts to get an instance synchronously if it already exists and is ready.\n * For request-scoped services, checks this container's context first.\n * For other services, delegates to the parent container.\n *\n * Returns null if the instance doesn't exist or is not yet ready (still creating).\n */\n tryGetSync<T>(token: any, args?: any): T | null {\n const tokenProcessor = this.parent.getServiceLocator().getTokenProcessor()\n const actualToken = tokenProcessor.normalizeToken(token)\n\n // Check if this is a request-scoped service\n if (this.isRequestScoped(actualToken)) {\n const serviceLocator = this.parent.getServiceLocator()\n const instanceName = serviceLocator.getInstanceIdentifier(token, args)\n const holder = this.requestContextHolder.get(instanceName)\n // Only return if holder exists AND is in Created status\n if (\n holder &&\n holder.status === InstanceStatus.Created\n ) {\n return holder.instance as T\n }\n return null\n }\n\n // Delegate to parent for non-request-scoped\n return this.parent.tryGetSync(token, args)\n }\n\n /**\n * Checks if a token is for a request-scoped service.\n */\n private isRequestScoped(token: any): boolean {\n // Handle BoundInjectionToken and FactoryInjectionToken using TokenProcessor\n const tokenProcessor = this.parent.getServiceLocator().getTokenProcessor()\n const realToken = tokenProcessor.getRealToken(token)\n\n if (!this.registry.has(realToken)) {\n return false\n }\n\n const record = this.registry.get(realToken)\n return record.scope === InjectableScope.Request\n }\n\n /**\n * Resolves a request-scoped service from this container's context.\n * Uses locking to prevent duplicate initialization during concurrent resolution.\n */\n private async resolveRequestScoped(token: any, args: unknown): Promise<any> {\n // Get the instance name\n const serviceLocator = this.parent.getServiceLocator()\n const instanceName = serviceLocator.getInstanceIdentifier(token, args)\n\n // Check if we already have this instance (or one is being created)\n const existingHolder = this.requestContextHolder.get(instanceName)\n if (existingHolder) {\n // Wait for the holder to be ready if it's still being created\n // This prevents race conditions where multiple concurrent calls\n // might try to create the same service\n const [error, readyHolder] =\n await BaseHolderManager.waitForHolderReady(existingHolder)\n if (error) {\n throw error\n }\n return readyHolder.instance\n }\n\n // Create new instance using parent's resolution mechanism\n // but store it in our request context\n return this.parent.resolveForRequest(token, args, this)\n }\n\n /**\n * Stores an instance in the request context.\n * Called by Container during request-scoped service resolution.\n */\n storeRequestInstance(\n instanceName: string,\n instance: any,\n holder: InstanceHolder,\n ): void {\n this.requestContextHolder.addInstance(instanceName, instance, holder)\n }\n\n /**\n * Gets an existing instance from the request context.\n * Called by Container during resolution to check for existing instances.\n */\n getRequestInstance(\n instanceName: string,\n ): InstanceHolder | undefined {\n return this.requestContextHolder.get(instanceName)\n }\n\n /**\n * Generates a prefixed event name for request-scoped services.\n * Format: {requestId}:{instanceName}\n */\n getPrefixedEventName(instanceName: string): string {\n return `${this.requestId}:${instanceName}`\n }\n}\n","import type { HolderManager } from './holder-manager.mjs'\nimport type {\n HolderGetResult,\n IHolderStorage,\n} from './holder-storage.interface.mjs'\nimport type { InstanceHolder } from './instance-holder.mjs'\n\nimport { InjectableScope, InjectableType } from '../../enums/index.mjs'\nimport { DIErrorCode } from '../../errors/index.mjs'\n\n/**\n * Storage implementation for Singleton-scoped services.\n *\n * Wraps a HolderManager instance and provides the IHolderStorage interface.\n * This allows the InstanceResolver to work with singleton storage\n * using the same interface as request-scoped storage.\n */\nexport class SingletonStorage implements IHolderStorage {\n readonly scope = InjectableScope.Singleton\n\n constructor(private readonly manager: HolderManager) {}\n\n get<T = unknown>(instanceName: string): HolderGetResult<T> {\n const [error, holder] = this.manager.get(instanceName)\n\n if (!error) {\n return [undefined, holder as InstanceHolder<T>]\n }\n\n // Handle different error types\n switch (error.code) {\n case DIErrorCode.InstanceNotFound:\n return null\n\n case DIErrorCode.InstanceDestroying:\n return [error, holder as InstanceHolder<T> | undefined]\n\n default:\n return [error]\n }\n }\n\n set(instanceName: string, holder: InstanceHolder): void {\n this.manager.set(instanceName, holder)\n }\n\n delete(instanceName: string): boolean {\n return this.manager.delete(instanceName)\n }\n\n createHolder<T>(\n instanceName: string,\n type: InjectableType,\n deps: Set<string>,\n ): [\n ReturnType<typeof Promise.withResolvers<[undefined, T]>>,\n InstanceHolder<T>,\n ] {\n return this.manager.createCreatingHolder<T>(\n instanceName,\n type,\n this.scope,\n deps,\n )\n }\n\n handles(scope: InjectableScope): boolean {\n return scope === InjectableScope.Singleton\n }\n\n // ============================================================================\n // ITERATION AND QUERY\n // ============================================================================\n\n getAllNames(): string[] {\n return this.manager.getAllNames()\n }\n\n forEach(\n callback: (name: string, holder: InstanceHolder) => void,\n ): void {\n for (const [name, holder] of this.manager.filter(() => true)) {\n callback(name, holder)\n }\n }\n\n findByInstance(instance: unknown): InstanceHolder | null {\n for (const [, holder] of this.manager.filter(\n (h) => h.instance === instance,\n )) {\n return holder\n }\n return null\n }\n\n findDependents(instanceName: string): string[] {\n const dependents: string[] = []\n for (const [name, holder] of this.manager.filter(() => true)) {\n if (holder.deps.has(instanceName)) {\n dependents.push(name)\n }\n }\n return dependents\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-empty-object-type */\nimport type { z, ZodObject, ZodOptional } from 'zod/v4'\n\nimport type { ScopedContainer } from '../../container/scoped-container.mjs'\nimport type { IContainer } from '../../interfaces/container.interface.mjs'\nimport type {\n AnyInjectableType,\n InjectionTokenSchemaType,\n InjectionTokenType,\n} from '../../token/injection-token.mjs'\nimport type { Registry } from '../../token/registry.mjs'\nimport type { FactoryContext } from '../context/factory-context.mjs'\nimport type { HolderManager } from '../holder/holder-manager.mjs'\nimport type { IHolderStorage } from '../holder/holder-storage.interface.mjs'\nimport type { InstanceHolder } from '../holder/instance-holder.mjs'\nimport type { Instantiator } from './instantiator.mjs'\nimport type { ServiceLocator } from './service-locator.mjs'\nimport type { TokenProcessor } from './token-processor.mjs'\n\nimport { InjectableScope } from '../../enums/index.mjs'\nimport { DIError, DIErrorCode } from '../../errors/index.mjs'\nimport {\n BoundInjectionToken,\n FactoryInjectionToken,\n InjectionToken,\n} from '../../token/injection-token.mjs'\nimport {\n getCurrentResolutionContext,\n withResolutionContext,\n} from '../context/resolution-context.mjs'\nimport { BaseHolderManager } from '../holder/base-holder-manager.mjs'\nimport { InstanceStatus } from '../holder/instance-holder.mjs'\nimport { SingletonStorage } from '../holder/singleton-storage.mjs'\n\n/**\n * Resolves instances from tokens, handling caching, creation, and scope rules.\n *\n * Uses the Storage Strategy pattern for unified singleton/request-scoped handling.\n * Coordinates with Instantiator for actual service creation.\n */\nexport class InstanceResolver {\n private readonly singletonStorage: IHolderStorage\n\n constructor(\n private readonly registry: Registry,\n private readonly manager: HolderManager,\n private readonly instantiator: Instantiator,\n private readonly tokenProcessor: TokenProcessor,\n private readonly logger: Console | null = null,\n private readonly serviceLocator: ServiceLocator,\n ) {\n this.singletonStorage = new SingletonStorage(manager)\n }\n\n // ============================================================================\n // PUBLIC RESOLUTION METHODS\n // ============================================================================\n\n /**\n * Resolves an instance for the given token and arguments.\n * This method is used for singleton and transient services.\n *\n * @param token The injection token\n * @param args Optional arguments\n * @param contextContainer The container to use for creating FactoryContext\n */\n async resolveInstance(\n token: AnyInjectableType,\n args: any,\n contextContainer: IContainer,\n ): Promise<[undefined, any] | [DIError]> {\n return this.resolveWithStorage(\n token,\n args,\n contextContainer,\n this.singletonStorage,\n )\n }\n\n /**\n * Resolves a request-scoped instance for a ScopedContainer.\n * The service will be stored in the ScopedContainer's request context.\n *\n * @param token The injection token\n * @param args Optional arguments\n * @param scopedContainer The ScopedContainer that owns the request context\n */\n async resolveRequestScopedInstance(\n token: AnyInjectableType,\n args: any,\n scopedContainer: ScopedContainer,\n ): Promise<[undefined, any] | [DIError]> {\n // Use the cached storage from ScopedContainer\n return this.resolveWithStorage(\n token,\n args,\n scopedContainer,\n scopedContainer.getHolderStorage(),\n scopedContainer,\n )\n }\n\n // ============================================================================\n // UNIFIED RESOLUTION (Storage Strategy Pattern)\n // ============================================================================\n\n /**\n * Unified resolution method that works with any IHolderStorage.\n * This eliminates duplication between singleton and request-scoped resolution.\n *\n * IMPORTANT: The check-and-store logic is carefully designed to avoid race conditions.\n * The storage check and holder creation must happen synchronously (no awaits between).\n *\n * @param token The injection token\n * @param args Optional arguments\n * @param contextContainer The container for FactoryContext\n * @param storage The storage strategy to use\n * @param scopedContainer Optional scoped container for request-scoped services\n */\n private async resolveWithStorage(\n token: AnyInjectableType,\n args: any,\n contextContainer: IContainer,\n storage: IHolderStorage,\n scopedContainer?: ScopedContainer,\n ): Promise<[undefined, any] | [DIError]> {\n // Step 1: Resolve token and prepare instance name\n const [err, data] = await this.resolveTokenAndPrepareInstanceName(\n token,\n args,\n contextContainer,\n )\n if (err) {\n return [err]\n }\n\n const { instanceName, validatedArgs, realToken } = data!\n\n // Step 2: Check for existing holder SYNCHRONOUSLY (no await between check and store)\n // This is critical for preventing race conditions with concurrent resolution\n const getResult = storage.get(instanceName)\n\n if (getResult !== null) {\n const [error, holder] = getResult\n if (!error && holder) {\n // Found existing holder - wait for it to be ready\n const readyResult = await this.waitForInstanceReady(holder)\n if (readyResult[0]) {\n return [readyResult[0]]\n }\n return [undefined, readyResult[1]!.instance]\n }\n // Handle error states (destroying, etc.)\n if (error) {\n const handledResult = await this.handleStorageError(\n instanceName,\n error,\n holder,\n storage,\n )\n if (handledResult) {\n return handledResult\n }\n }\n }\n\n // Step 3: Create new instance and store it\n // NOTE: Holder is stored synchronously inside createAndStoreInstance before any await\n const [createError, holder] = await this.createAndStoreInstance(\n instanceName,\n realToken,\n validatedArgs,\n contextContainer,\n storage,\n scopedContainer,\n )\n if (createError) {\n return [createError]\n }\n\n return [undefined, holder!.instance]\n }\n\n /**\n * Handles storage error states (destroying, error, etc.).\n * Returns a result if handled, null if should proceed with creation.\n */\n private async handleStorageError(\n instanceName: string,\n error: DIError,\n holder: InstanceHolder | undefined,\n storage: IHolderStorage,\n ): Promise<[undefined, any] | [DIError] | null> {\n switch (error.code) {\n case DIErrorCode.InstanceDestroying:\n // Wait for destruction then retry\n this.logger?.log(\n `[InstanceResolver] Instance ${instanceName} is being destroyed, waiting...`,\n )\n if (holder?.destroyPromise) {\n await holder.destroyPromise\n }\n // Re-check after destruction\n const newResult = storage.get(instanceName)\n if (newResult !== null && !newResult[0]) {\n const readyResult = await this.waitForInstanceReady(newResult[1]!)\n if (readyResult[0]) {\n return [readyResult[0]]\n }\n return [undefined, readyResult[1]!.instance]\n }\n return null // Proceed with creation\n\n default:\n return [error]\n }\n }\n\n /**\n * Creates a new instance and stores it using the provided storage strategy.\n * This unified method replaces instantiateServiceFromRegistry and createRequestScopedInstance.\n *\n * For transient services, the instance is created but not stored (no caching).\n */\n private async createAndStoreInstance<Instance>(\n instanceName: string,\n realToken: InjectionToken<Instance, any>,\n args: any,\n contextContainer: IContainer,\n storage: IHolderStorage,\n scopedContainer?: ScopedContainer,\n ): Promise<[undefined, InstanceHolder<Instance>] | [DIError]> {\n this.logger?.log(\n `[InstanceResolver]#createAndStoreInstance() Creating instance for ${instanceName}`,\n )\n\n if (!this.registry.has(realToken)) {\n return [DIError.factoryNotFound(realToken.name.toString())]\n }\n\n const ctx = this.createFactoryContext(contextContainer)\n const record = this.registry.get<Instance, any>(realToken)\n const { scope, type } = record\n\n // For transient services, don't use storage locking - create directly\n if (scope === InjectableScope.Transient) {\n return this.createTransientInstance(instanceName, record, args, ctx)\n }\n\n // Create holder in \"Creating\" state using registry scope, not storage scope\n const [deferred, holder] = this.manager.createCreatingHolder<Instance>(\n instanceName,\n type,\n scope,\n ctx.deps,\n )\n\n // Store holder immediately (for lock mechanism)\n storage.set(instanceName, holder)\n\n // Create a getHolder function that looks up holders from both the manager and storage\n const getHolder = (name: string): InstanceHolder | undefined => {\n // First check the storage (which might be request-scoped)\n const storageResult = storage.get(name)\n if (storageResult !== null) {\n const [, storageHolder] = storageResult\n if (storageHolder) return storageHolder\n }\n // Fall back to the singleton manager\n const [, managerHolder] = this.manager.get(name)\n return managerHolder\n }\n\n // Start async instantiation within the resolution context\n // This allows circular dependency detection to track the waiter\n withResolutionContext(holder, getHolder, () => {\n this.instantiator\n .instantiateService(ctx, record, args)\n .then(async (result: [undefined, Instance] | [DIError]) => {\n const [error, instance] =\n result.length === 2 ? result : [result[0], undefined]\n await this.handleInstantiationResult(\n instanceName,\n holder,\n ctx,\n deferred,\n scope,\n error,\n instance,\n scopedContainer,\n )\n })\n .catch(async (error: Error) => {\n await this.handleInstantiationError(\n instanceName,\n holder,\n deferred,\n scope,\n error,\n )\n })\n .catch(() => {\n // Suppress unhandled rejections from the async chain.\n // Errors are communicated to awaiters via deferred.reject() which\n // rejects holder.creationPromise. This catch is a safety net for\n // any errors that might occur in the error handling itself.\n })\n })\n\n // Wait for instance to be ready\n return this.waitForInstanceReady(holder)\n }\n\n /**\n * Creates a transient instance without storage or locking.\n * Each call creates a new instance.\n */\n private async createTransientInstance<Instance>(\n instanceName: string,\n record: any,\n args: any,\n ctx: FactoryContext & {\n deps: Set<string>\n getDestroyListeners: () => (() => void)[]\n },\n ): Promise<[undefined, InstanceHolder<Instance>] | [DIError]> {\n this.logger?.log(\n `[InstanceResolver]#createTransientInstance() Creating transient instance for ${instanceName}`,\n )\n\n // Create a temporary holder for resolution context (transient instances can still have deps)\n const tempHolder: InstanceHolder<Instance> = {\n status: InstanceStatus.Creating,\n name: instanceName,\n instance: null,\n creationPromise: null,\n destroyPromise: null,\n type: record.type,\n scope: InjectableScope.Transient,\n deps: ctx.deps,\n destroyListeners: [],\n createdAt: Date.now(),\n waitingFor: new Set(),\n }\n\n // Create a getHolder function for resolution context\n const getHolder = (name: string): InstanceHolder | undefined => {\n const [, managerHolder] = this.manager.get(name)\n return managerHolder\n }\n\n // Run instantiation within resolution context for cycle detection\n const [error, instance] = await withResolutionContext(\n tempHolder,\n getHolder,\n () => this.instantiator.instantiateService(ctx, record, args),\n )\n\n if (error) {\n return [error as DIError]\n }\n\n // Create a holder for the transient instance (not stored, just for return consistency)\n const holder: InstanceHolder<Instance> = {\n status: InstanceStatus.Created,\n name: instanceName,\n instance: instance as Instance,\n creationPromise: null,\n destroyPromise: null,\n type: record.type,\n scope: InjectableScope.Transient,\n deps: ctx.deps,\n destroyListeners: ctx.getDestroyListeners(),\n createdAt: Date.now(),\n waitingFor: new Set(),\n }\n\n return [undefined, holder]\n }\n\n /**\n * Gets a synchronous instance (for sync operations).\n */\n getSyncInstance<\n Instance,\n Schema extends InjectionTokenSchemaType | undefined,\n >(\n token: AnyInjectableType,\n args: Schema extends ZodObject\n ? z.input<Schema>\n : Schema extends ZodOptional<ZodObject>\n ? z.input<Schema> | undefined\n : undefined,\n contextContainer: IContainer,\n ): Instance | null {\n const [err, { actualToken, validatedArgs }] =\n this.tokenProcessor.validateAndResolveTokenArgs(token, args)\n if (err) {\n return null\n }\n const instanceName = this.tokenProcessor.generateInstanceName(\n actualToken,\n validatedArgs,\n )\n\n // Check if this is a ScopedContainer and the service is request-scoped\n if ('getRequestInstance' in contextContainer) {\n const scopedContainer = contextContainer as ScopedContainer\n const requestHolder = scopedContainer.getRequestInstance(instanceName)\n if (requestHolder) {\n return requestHolder.instance as Instance\n }\n }\n\n // Try singleton manager\n const [error, holder] = this.manager.get(instanceName)\n if (error) {\n return null\n }\n return holder.instance as Instance\n }\n\n /**\n * Internal method to resolve token args and create instance name.\n * Handles factory token resolution and validation.\n */\n private async resolveTokenAndPrepareInstanceName(\n token: AnyInjectableType,\n args: any,\n contextContainer: IContainer,\n ): Promise<\n | [\n undefined,\n {\n instanceName: string\n validatedArgs: any\n actualToken: InjectionTokenType\n realToken: InjectionToken<any, any>\n },\n ]\n | [DIError]\n > {\n const [err, { actualToken, validatedArgs }] =\n this.tokenProcessor.validateAndResolveTokenArgs(token, args)\n if (err instanceof DIError && err.code === DIErrorCode.UnknownError) {\n return [err]\n } else if (\n err instanceof DIError &&\n err.code === DIErrorCode.FactoryTokenNotResolved &&\n actualToken instanceof FactoryInjectionToken\n ) {\n this.logger?.log(\n `[InstanceResolver]#resolveTokenAndPrepareInstanceName() Factory token not resolved, resolving it`,\n )\n await actualToken.resolve(this.createFactoryContext(contextContainer))\n return this.resolveTokenAndPrepareInstanceName(\n token,\n undefined,\n contextContainer,\n )\n }\n const instanceName = this.tokenProcessor.generateInstanceName(\n actualToken,\n validatedArgs,\n )\n // Determine the real token (the actual InjectionToken that will be used for resolution)\n const realToken =\n actualToken instanceof BoundInjectionToken ||\n actualToken instanceof FactoryInjectionToken\n ? actualToken.token\n : actualToken\n return [undefined, { instanceName, validatedArgs, actualToken, realToken }]\n }\n\n // ============================================================================\n // INSTANTIATION HANDLERS\n // ============================================================================\n\n /**\n * Waits for an instance holder to be ready and returns the appropriate result.\n * Uses the shared utility from BaseHolderManager.\n * Passes the current resolution context for circular dependency detection.\n */\n private waitForInstanceReady<T>(\n holder: InstanceHolder<T>,\n ): Promise<[undefined, InstanceHolder<T>] | [DIError]> {\n // Get the current resolution context (if we're inside an instantiation)\n const ctx = getCurrentResolutionContext()\n\n return BaseHolderManager.waitForHolderReady(\n holder,\n ctx?.waiterHolder,\n ctx?.getHolder,\n )\n }\n\n /**\n * Handles the result of service instantiation.\n */\n private async handleInstantiationResult(\n instanceName: string,\n holder: InstanceHolder<any>,\n ctx: FactoryContext & {\n deps: Set<string>\n getDestroyListeners: () => (() => void)[]\n },\n deferred: any,\n scope: InjectableScope,\n error: any,\n instance: any,\n scopedContainer?: ScopedContainer,\n ): Promise<void> {\n holder.destroyListeners = ctx.getDestroyListeners()\n holder.creationPromise = null\n\n if (error) {\n await this.handleInstantiationError(\n instanceName,\n holder,\n deferred,\n scope,\n error,\n )\n } else {\n await this.handleInstantiationSuccess(\n instanceName,\n holder,\n ctx,\n deferred,\n instance,\n scopedContainer,\n )\n }\n }\n\n /**\n * Handles successful service instantiation.\n */\n private async handleInstantiationSuccess(\n instanceName: string,\n holder: InstanceHolder<any>,\n ctx: FactoryContext & {\n deps: Set<string>\n getDestroyListeners: () => (() => void)[]\n },\n deferred: any,\n instance: any,\n scopedContainer?: ScopedContainer,\n ): Promise<void> {\n holder.instance = instance\n holder.status = InstanceStatus.Created\n\n // Set up dependency invalidation listeners\n if (ctx.deps.size > 0) {\n ctx.deps.forEach((dependency: string) => {\n holder.destroyListeners.push(\n this.serviceLocator.getEventBus().on(dependency, 'destroy', () => {\n this.logger?.log(\n `[InstanceResolver] Dependency ${dependency} destroyed, invalidating ${instanceName}`,\n )\n this.serviceLocator.getInvalidator().invalidate(instanceName)\n }),\n )\n\n // For request-scoped services, also listen with prefixed event name\n if (scopedContainer) {\n const prefixedDependency =\n scopedContainer.getPrefixedEventName(dependency)\n holder.destroyListeners.push(\n this.serviceLocator\n .getEventBus()\n .on(prefixedDependency, 'destroy', () => {\n this.logger?.log(\n `[InstanceResolver] Request-scoped dependency ${dependency} destroyed, invalidating ${instanceName}`,\n )\n // For request-scoped, we need to invalidate within the scoped container\n scopedContainer.invalidate(instance)\n }),\n )\n }\n })\n }\n\n // Note: Event emission would need access to the event bus\n this.logger?.log(\n `[InstanceResolver] Instance ${instanceName} created successfully`,\n )\n deferred.resolve([undefined, instance])\n }\n\n /**\n * Handles service instantiation errors.\n */\n private async handleInstantiationError(\n instanceName: string,\n holder: InstanceHolder<any>,\n deferred: any,\n scope: InjectableScope,\n error: any,\n ): Promise<void> {\n this.logger?.error(\n `[InstanceResolver] Error creating instance for ${instanceName}`,\n error,\n )\n\n holder.status = InstanceStatus.Error\n holder.instance = error\n holder.creationPromise = null\n\n if (scope === InjectableScope.Singleton) {\n this.logger?.log(\n `[InstanceResolver] Singleton ${instanceName} failed, will be invalidated`,\n )\n // Fire-and-forget invalidation - don't await as it could cause deadlocks\n // Suppress any potential rejections since the primary error is already handled\n this.serviceLocator\n .getInvalidator()\n .invalidate(instanceName)\n .catch(() => {\n // Suppress - primary error is communicated via deferred.reject()\n })\n }\n\n deferred.reject(error)\n }\n\n // ============================================================================\n // FACTORY CONTEXT\n // ============================================================================\n\n /**\n * Creates a factory context for dependency injection during service instantiation.\n */\n private createFactoryContext(contextContainer: IContainer): FactoryContext & {\n getDestroyListeners: () => (() => void)[]\n deps: Set<string>\n } {\n return this.tokenProcessor.createFactoryContext(contextContainer)\n }\n}\n","import type { FactoryRecord } from '../../token/registry.mjs'\nimport type { Injectors } from '../../utils/get-injectors.mjs'\nimport type { FactoryContext } from '../context/factory-context.mjs'\n\nimport { InjectableType } from '../../enums/index.mjs'\nimport { DIError } from '../../errors/index.mjs'\n\n/**\n * Creates service instances from registry records.\n *\n * Handles both class-based (@Injectable) and factory-based (@Factory) services,\n * managing the instantiation lifecycle including sync initialization retries\n * and lifecycle hook invocation (onServiceInit, onServiceDestroy).\n */\nexport class Instantiator {\n constructor(private readonly injectors: Injectors) {}\n\n /**\n * Instantiates a service based on its registry record.\n * @param ctx The factory context for dependency injection\n * @param record The factory record from the registry\n * @param args Optional arguments for the service\n * @returns Promise resolving to [undefined, instance] or [error]\n */\n async instantiateService<T>(\n ctx: FactoryContext,\n record: FactoryRecord<T, any>,\n args: any = undefined,\n ): Promise<[undefined, T] | [DIError]> {\n try {\n switch (record.type) {\n case InjectableType.Class:\n return this.instantiateClass(ctx, record, args)\n case InjectableType.Factory:\n return this.instantiateFactory(ctx, record, args)\n default:\n throw DIError.unknown(\n `[Instantiator] Unknown service type: ${record.type}`,\n )\n }\n } catch (error) {\n return [error instanceof DIError ? error : DIError.unknown(String(error))]\n }\n }\n\n /**\n * Instantiates a class-based service (Injectable decorator).\n * @param ctx The factory context for dependency injection\n * @param record The factory record from the registry\n * @param args Optional arguments for the service constructor\n * @returns Promise resolving to [undefined, instance] or [error]\n */\n private async instantiateClass<T>(\n ctx: FactoryContext,\n record: FactoryRecord<T, any>,\n args: any,\n ): Promise<[undefined, T] | [DIError]> {\n try {\n const tryLoad = this.injectors.wrapSyncInit(() => {\n const original = this.injectors.provideFactoryContext(ctx)\n let result = new record.target(...(args ? [args] : []))\n this.injectors.provideFactoryContext(original)\n return result\n })\n\n let [instance, promises, injectState] = tryLoad()\n if (promises.length > 0) {\n const results = await Promise.allSettled(promises)\n if (results.some((result) => result.status === 'rejected')) {\n throw DIError.unknown(\n `[Instantiator] Service ${record.target.name} cannot be instantiated.`,\n )\n }\n const newRes = tryLoad(injectState)\n instance = newRes[0]\n promises = newRes[1]\n }\n\n if (promises.length > 0) {\n console.error(`[Instantiator] ${record.target.name} has problem with it's definition.\n\n One or more of the dependencies are registered as a InjectableScope.Instance and are used with inject.\n\n Please use inject asyncInject of inject to load those dependencies.`)\n throw DIError.unknown(\n `[Instantiator] Service ${record.target.name} cannot be instantiated.`,\n )\n }\n\n // Handle lifecycle hooks\n if ('onServiceInit' in instance) {\n await (instance as any).onServiceInit()\n }\n if ('onServiceDestroy' in instance) {\n ctx.addDestroyListener(async () => {\n await (instance as any).onServiceDestroy()\n })\n }\n\n return [undefined, instance]\n } catch (error) {\n return [error instanceof DIError ? error : DIError.unknown(String(error))]\n }\n }\n\n /**\n * Instantiates a factory-based service (Factory decorator).\n * @param ctx The factory context for dependency injection\n * @param record The factory record from the registry\n * @param args Optional arguments for the factory\n * @returns Promise resolving to [undefined, instance] or [error]\n */\n private async instantiateFactory<T>(\n ctx: FactoryContext,\n record: FactoryRecord<T, any>,\n args: any,\n ): Promise<[undefined, T] | [DIError]> {\n try {\n const tryLoad = this.injectors.wrapSyncInit(() => {\n const original = this.injectors.provideFactoryContext(ctx)\n let result = new record.target()\n this.injectors.provideFactoryContext(original)\n return result\n })\n\n let [builder, promises, injectState] = tryLoad()\n if (promises.length > 0) {\n const results = await Promise.allSettled(promises)\n if (results.some((result) => result.status === 'rejected')) {\n throw DIError.unknown(\n `[Instantiator] Service ${record.target.name} cannot be instantiated.`,\n )\n }\n const newRes = tryLoad(injectState)\n builder = newRes[0]\n promises = newRes[1]\n }\n\n if (promises.length > 0) {\n console.error(`[Instantiator] ${record.target.name} has problem with it's definition.\n\n One or more of the dependencies are registered as a InjectableScope.Instance and are used with inject.\n\n Please use asyncInject instead of inject to load those dependencies.`)\n throw DIError.unknown(\n `[Instantiator] Service ${record.target.name} cannot be instantiated.`,\n )\n }\n\n if (typeof builder.create !== 'function') {\n throw DIError.unknown(\n `[Instantiator] Factory ${record.target.name} does not implement the create method.`,\n )\n }\n\n const instance = await builder.create(ctx, args)\n return [undefined, instance]\n } catch (error) {\n return [error instanceof DIError ? error : DIError.unknown(String(error))]\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { IHolderStorage } from '../holder/holder-storage.interface.mjs'\nimport type { LifecycleEventBus } from '../lifecycle/lifecycle-event-bus.mjs'\nimport type { InstanceHolder } from '../holder/instance-holder.mjs'\nimport type { HolderManager } from '../holder/holder-manager.mjs'\n\nimport { InstanceStatus } from '../holder/instance-holder.mjs'\nimport { SingletonStorage } from '../holder/singleton-storage.mjs'\n\nexport interface ClearAllOptions {\n /** Maximum number of invalidation rounds to prevent infinite loops (default: 10) */\n maxRounds?: number\n /** Whether to wait for all services to settle before starting (default: true) */\n waitForSettlement?: boolean\n}\n\nexport interface InvalidationOptions {\n /** Whether to emit events after invalidation (default: true for singletons) */\n emitEvents?: boolean\n /** Custom event emitter function */\n onInvalidated?: (instanceName: string) => Promise<void>\n /** Whether to cascade invalidation to dependents (default: true) */\n cascade?: boolean\n /** Internal: tracks services being invalidated in the current call chain to prevent circular loops */\n _invalidating?: Set<string>\n}\n\n/**\n * Manages graceful service cleanup with dependency-aware invalidation.\n *\n * Ensures services are destroyed in the correct order based on their dependencies.\n * Works with any IHolderStorage implementation, enabling unified invalidation\n * for both singleton and request-scoped services.\n */\nexport class Invalidator {\n private readonly storage: IHolderStorage\n\n constructor(\n manager: HolderManager,\n private readonly eventBus: LifecycleEventBus | null,\n private readonly logger: Console | null = null,\n ) {\n this.storage = new SingletonStorage(manager)\n }\n\n /**\n * Invalidates a service and all its dependencies.\n * Works with the configured storage (singleton by default).\n */\n invalidate(service: string, round = 1): Promise<any> {\n return this.invalidateWithStorage(service, this.storage, round)\n }\n\n /**\n * Invalidates a service using a specific storage.\n * This allows request-scoped invalidation using a RequestStorage.\n *\n * @param service The instance name to invalidate\n * @param storage The storage to use for this invalidation\n * @param round Current invalidation round (for recursion limiting)\n * @param options Additional options for invalidation behavior\n */\n async invalidateWithStorage(\n service: string,\n storage: IHolderStorage,\n round = 1,\n options: InvalidationOptions = {},\n ): Promise<void> {\n const { cascade = true, _invalidating = new Set<string>() } = options\n\n // Prevent infinite recursion from circular dependencies\n if (_invalidating.has(service)) {\n this.logger?.log(\n `[Invalidator] Skipping ${service} - already being invalidated in this chain`,\n )\n return\n }\n\n this.logger?.log(\n `[Invalidator] Starting invalidation process for ${service}`,\n )\n\n const result = storage.get(service)\n if (result === null) {\n return\n }\n\n // Mark this service as being invalidated\n _invalidating.add(service)\n\n // Pass the tracking set to cascaded invalidations\n const optionsWithTracking = { ...options, _invalidating }\n\n // Cascade invalidation: first invalidate all services that depend on this one\n if (cascade) {\n const dependents = storage.findDependents(service)\n for (const dependentName of dependents) {\n await this.invalidateWithStorage(dependentName, storage, round, optionsWithTracking)\n }\n }\n\n const [, holder] = result\n if (holder) {\n await this.invalidateHolderWithStorage(service, holder, storage, round, optionsWithTracking)\n }\n }\n\n /**\n * Gracefully clears all services using invalidation logic.\n * This method respects service dependencies and ensures proper cleanup order.\n * Services that depend on others will be invalidated first, then their dependencies.\n */\n async clearAll(options: ClearAllOptions = {}): Promise<void> {\n return this.clearAllWithStorage(this.storage, options)\n }\n\n /**\n * Gracefully clears all services in a specific storage.\n * This allows clearing request-scoped services using a RequestStorage.\n */\n async clearAllWithStorage(\n storage: IHolderStorage,\n options: ClearAllOptions = {},\n ): Promise<void> {\n const { maxRounds = 10, waitForSettlement = true } = options\n\n this.logger?.log(\n '[Invalidator] Starting graceful clearing of all services',\n )\n\n // Wait for all services to settle if requested\n if (waitForSettlement) {\n this.logger?.log(\n '[Invalidator] Waiting for all services to settle...',\n )\n await this.readyWithStorage(storage)\n }\n\n // Get all service names that need to be cleared\n const allServiceNames = storage.getAllNames()\n\n if (allServiceNames.length === 0) {\n this.logger?.log('[Invalidator] No services to clear')\n } else {\n this.logger?.log(\n `[Invalidator] Found ${allServiceNames.length} services to clear: ${allServiceNames.join(', ')}`,\n )\n\n // Clear services using dependency-aware invalidation\n await this.clearServicesWithDependencyAwarenessForStorage(\n allServiceNames,\n maxRounds,\n storage,\n )\n }\n\n this.logger?.log('[Invalidator] Graceful clearing completed')\n }\n\n /**\n * Waits for all services to settle (either created, destroyed, or error state).\n */\n async ready(): Promise<void> {\n return this.readyWithStorage(this.storage)\n }\n\n /**\n * Waits for all services in a specific storage to settle.\n */\n async readyWithStorage(storage: IHolderStorage): Promise<void> {\n const holders: InstanceHolder<any>[] = []\n storage.forEach((_: string, holder: InstanceHolder) => holders.push(holder))\n await Promise.all(\n holders.map((holder) => this.waitForHolderToSettle(holder)),\n )\n }\n\n // ============================================================================\n // INTERNAL INVALIDATION HELPERS\n // ============================================================================\n\n /**\n * Invalidates a single holder using a specific storage.\n */\n private async invalidateHolderWithStorage(\n key: string,\n holder: InstanceHolder<any>,\n storage: IHolderStorage,\n round: number,\n options: InvalidationOptions = {},\n ): Promise<void> {\n const { emitEvents = true, onInvalidated } = options\n\n await this.invalidateHolderByStatus(holder, round, {\n context: key,\n onCreationError: () =>\n this.logger?.error(\n `[Invalidator] ${key} creation triggered too many invalidation rounds`,\n ),\n onRecursiveInvalidate: () =>\n this.invalidateWithStorage(key, storage, round + 1, options),\n onDestroy: () =>\n this.destroyHolderWithStorage(key, holder, storage, emitEvents, onInvalidated),\n })\n }\n\n /**\n * Common invalidation logic for holders based on their status.\n */\n private async invalidateHolderByStatus(\n holder: InstanceHolder<any>,\n round: number,\n options: {\n context: string\n onCreationError: () => void\n onRecursiveInvalidate: () => Promise<void>\n onDestroy: () => Promise<void>\n },\n ): Promise<void> {\n switch (holder.status) {\n case InstanceStatus.Destroying:\n await holder.destroyPromise\n break\n\n case InstanceStatus.Creating:\n await holder.creationPromise\n if (round > 3) {\n options.onCreationError()\n return\n }\n await options.onRecursiveInvalidate()\n break\n\n default:\n await options.onDestroy()\n break\n }\n }\n\n /**\n * Destroys a holder using a specific storage.\n */\n private async destroyHolderWithStorage(\n key: string,\n holder: InstanceHolder<any>,\n storage: IHolderStorage,\n emitEvents: boolean,\n onInvalidated?: (instanceName: string) => Promise<void>,\n ): Promise<void> {\n holder.status = InstanceStatus.Destroying\n this.logger?.log(`[Invalidator] Invalidating ${key} and notifying listeners`)\n\n holder.destroyPromise = Promise.all(\n holder.destroyListeners.map((listener) => listener()),\n ).then(async () => {\n holder.destroyListeners = []\n holder.deps.clear()\n storage.delete(key)\n\n // Emit events if enabled and event bus exists\n if (emitEvents && this.eventBus) {\n await this.emitInstanceEvent(key, 'destroy')\n }\n\n // Call custom callback if provided\n if (onInvalidated) {\n await onInvalidated(key)\n }\n })\n\n await holder.destroyPromise\n }\n\n /**\n * Waits for a holder to settle (either created, destroyed, or error state).\n */\n private async waitForHolderToSettle(\n holder: InstanceHolder<any>,\n ): Promise<void> {\n switch (holder.status) {\n case InstanceStatus.Creating:\n await holder.creationPromise\n break\n case InstanceStatus.Destroying:\n await holder.destroyPromise\n break\n // Already settled states\n case InstanceStatus.Created:\n case InstanceStatus.Error:\n break\n }\n }\n\n /**\n * Clears services with dependency awareness for a specific storage.\n */\n private async clearServicesWithDependencyAwarenessForStorage(\n serviceNames: string[],\n maxRounds: number,\n storage: IHolderStorage,\n ): Promise<void> {\n const clearedServices = new Set<string>()\n let round = 1\n\n while (clearedServices.size < serviceNames.length && round <= maxRounds) {\n this.logger?.log(\n `[Invalidator] Clearing round ${round}/${maxRounds}, ${clearedServices.size}/${serviceNames.length} services cleared`,\n )\n\n // Find services that can be cleared in this round\n const servicesToClearThisRound = this.findServicesReadyForClearingInStorage(\n serviceNames,\n clearedServices,\n storage,\n )\n\n if (servicesToClearThisRound.length === 0) {\n // If no services can be cleared, try to clear remaining services anyway\n // This handles circular dependencies or other edge cases\n const remainingServices = serviceNames.filter(\n (name) => !clearedServices.has(name),\n )\n\n if (remainingServices.length > 0) {\n this.logger?.warn(\n `[Invalidator] No services ready for clearing, forcing cleanup of remaining: ${remainingServices.join(', ')}`,\n )\n await this.forceClearServicesInStorage(remainingServices, storage)\n remainingServices.forEach((name) => clearedServices.add(name))\n }\n break\n }\n\n // Clear services in this round\n const clearPromises = servicesToClearThisRound.map(\n async (serviceName) => {\n try {\n await this.invalidateWithStorage(serviceName, storage, round)\n clearedServices.add(serviceName)\n this.logger?.log(\n `[Invalidator] Successfully cleared service: ${serviceName}`,\n )\n } catch (error) {\n this.logger?.error(\n `[Invalidator] Error clearing service ${serviceName}:`,\n error,\n )\n // Still mark as cleared to avoid infinite loops\n clearedServices.add(serviceName)\n }\n },\n )\n\n await Promise.all(clearPromises)\n round++\n }\n\n if (clearedServices.size < serviceNames.length) {\n this.logger?.warn(\n `[Invalidator] Clearing completed after ${maxRounds} rounds, but ${serviceNames.length - clearedServices.size} services may not have been properly cleared`,\n )\n }\n }\n\n /**\n * Finds services that are ready to be cleared in the current round.\n * A service is ready if all its dependencies have already been cleared.\n */\n private findServicesReadyForClearingInStorage(\n allServiceNames: string[],\n clearedServices: Set<string>,\n storage: IHolderStorage,\n ): string[] {\n return allServiceNames.filter((serviceName) => {\n if (clearedServices.has(serviceName)) {\n return false // Already cleared\n }\n\n // Check if this service has any dependencies that haven't been cleared yet\n const result = storage.get(serviceName)\n if (result === null || result[0]) {\n return true // Service not found or in error state, can be cleared\n }\n\n const [, holder] = result\n // Check if all dependencies have been cleared\n const hasUnclearedDependencies = Array.from(holder!.deps).some(\n (dep) => !clearedServices.has(dep),\n )\n\n return !hasUnclearedDependencies\n })\n }\n\n /**\n * Force clears services that couldn't be cleared through normal dependency resolution.\n * This handles edge cases like circular dependencies.\n */\n private async forceClearServicesInStorage(\n serviceNames: string[],\n storage: IHolderStorage,\n ): Promise<void> {\n const promises = serviceNames.map(async (serviceName) => {\n try {\n // Directly destroy the holder without going through normal invalidation\n const result = storage.get(serviceName)\n if (result !== null && !result[0]) {\n const [, holder] = result\n await this.destroyHolderWithStorage(serviceName, holder!, storage, true)\n }\n } catch (error) {\n this.logger?.error(\n `[Invalidator] Error force clearing service ${serviceName}:`,\n error,\n )\n }\n })\n\n await Promise.all(promises)\n }\n\n /**\n * Emits events to listeners for instance lifecycle events.\n */\n private emitInstanceEvent(\n name: string,\n event: 'create' | 'destroy' = 'create',\n ) {\n if (!this.eventBus) {\n return Promise.resolve()\n }\n this.logger?.log(\n `[Invalidator]#emitInstanceEvent() Notifying listeners for ${name} with event ${event}`,\n )\n return this.eventBus.emit(name, event)\n }\n}\n","/* eslint-disable @typescript-eslint/no-empty-object-type */\n/* eslint-disable @typescript-eslint/no-unsafe-function-type */\n\ntype ListenersMap = Map<string, Map<string, Set<Function>>>\n\n/**\n * Event bus for service lifecycle events (create, destroy, etc.).\n *\n * Enables loose coupling between services by allowing them to subscribe\n * to lifecycle events of their dependencies without direct references.\n * Used primarily for invalidation cascading.\n */\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\nexport class LifecycleEventBus {\n private listeners: ListenersMap = new Map()\n constructor(private readonly logger: Console | null = null) {}\n\n on<Event extends string | `pre:${string}` | `post:${string}`>(\n ns: string,\n event: Event,\n listener: (event: Event) => void,\n ) {\n this.logger?.debug(`[LifecycleEventBus]#on(): ns:${ns} event:${event}`)\n if (!this.listeners.has(ns)) {\n this.listeners.set(ns, new Map())\n }\n\n const nsEvents = this.listeners.get(ns)!\n if (!nsEvents.has(event)) {\n nsEvents.set(event, new Set())\n }\n\n nsEvents.get(event)!.add(listener)\n\n return () => {\n nsEvents.get(event)?.delete(listener)\n if (nsEvents.get(event)?.size === 0) {\n nsEvents.delete(event)\n }\n if (nsEvents.size === 0) {\n this.listeners.delete(ns)\n }\n }\n }\n\n async emit(key: string, event: string) {\n if (!this.listeners.has(key)) {\n return\n }\n\n const events = this.listeners.get(key)!\n\n this.logger?.debug(`[LifecycleEventBus]#emit(): ${key}:${event}`)\n\n const res = await Promise.allSettled(\n [...(events.get(event) ?? [])!].map((listener) => listener(event)),\n ).then((results) => {\n const res = results\n .filter((result) => result.status === 'rejected')\n .map((result: PromiseRejectedResult) => {\n this.logger?.warn(\n `[LifecycleEventBus]#emit(): ${key}:${event} rejected with`,\n result.reason,\n )\n return result\n })\n\n if (res.length > 0) {\n return Promise.reject(res)\n }\n return results\n })\n return res\n }\n}\n","import type { InstanceHolder } from './instance-holder.mjs'\n\nimport { InjectableScope, InjectableType } from '../../enums/index.mjs'\nimport { DIError, DIErrorCode } from '../../errors/index.mjs'\nimport { BaseHolderManager } from './base-holder-manager.mjs'\nimport { InstanceStatus } from './instance-holder.mjs'\n\n/**\n * Manages the storage and retrieval of singleton instance holders.\n *\n * Provides CRUD operations and filtering for the holder map.\n * Handles holder state validation (destroying, error states) on retrieval.\n */\nexport class HolderManager extends BaseHolderManager {\n constructor(logger: Console | null = null) {\n super(logger)\n }\n\n get(\n name: string,\n ): [DIError, InstanceHolder] | [DIError] | [undefined, InstanceHolder] {\n const holder = this._holders.get(name)\n if (holder) {\n if (holder.status === InstanceStatus.Destroying) {\n this.logger?.log(\n `[HolderManager]#get() Instance ${holder.name} is destroying`,\n )\n return [DIError.instanceDestroying(holder.name), holder]\n } else if (holder.status === InstanceStatus.Error) {\n this.logger?.log(\n `[HolderManager]#get() Instance ${holder.name} is in error state`,\n )\n return [holder.instance as unknown as DIError, holder]\n }\n\n return [undefined, holder]\n } else {\n this.logger?.log(`[HolderManager]#get() Instance ${name} not found`)\n return [DIError.instanceNotFound(name)]\n }\n }\n\n set(name: string, holder: InstanceHolder): void {\n this._holders.set(name, holder)\n }\n\n has(name: string): [DIError] | [undefined, boolean] {\n const [error, holder] = this.get(name)\n if (!error) {\n return [undefined, true]\n }\n if (error.code === DIErrorCode.InstanceDestroying) {\n return [error]\n }\n return [undefined, !!holder]\n }\n\n // delete and filter methods are inherited from BaseHolderManager\n\n // createCreatingHolder method is inherited from BaseHolderManager\n\n /**\n * Creates a new holder with Created status and stores it.\n * This is useful for creating holders that already have their instance ready.\n * @param name The name of the instance\n * @param instance The actual instance to store\n * @param type The injectable type\n * @param scope The injectable scope\n * @param deps Optional set of dependencies\n * @returns The created holder\n */\n storeCreatedHolder<Instance>(\n name: string,\n instance: Instance,\n type: InjectableType,\n scope: InjectableScope,\n deps: Set<string> = new Set(),\n ): InstanceHolder<Instance> {\n const holder = this.createCreatedHolder(name, instance, type, scope, deps)\n\n this._holders.set(name, holder)\n\n return holder\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-empty-object-type */\n\nimport type { FactoryContext } from '../context/factory-context.mjs'\nimport type {\n AnyInjectableType,\n InjectionTokenType,\n} from '../../token/injection-token.mjs'\nimport type { IContainer } from '../../interfaces/container.interface.mjs'\n\nimport { DIError } from '../../errors/index.mjs'\nimport {\n BoundInjectionToken,\n FactoryInjectionToken,\n InjectionToken,\n} from '../../token/injection-token.mjs'\nimport { getInjectableToken } from '../../utils/index.mjs'\n\n/**\n * Handles token validation, normalization, and instance name generation.\n *\n * Provides utilities for resolving tokens to their underlying InjectionToken,\n * validating arguments against schemas, and generating unique instance identifiers.\n */\nexport class TokenProcessor {\n constructor(private readonly logger: Console | null = null) {}\n\n // ============================================================================\n // TOKEN NORMALIZATION\n // ============================================================================\n\n /**\n * Normalizes a token to an InjectionToken.\n * Handles class constructors by getting their injectable token.\n *\n * @param token A class constructor, InjectionToken, BoundInjectionToken, or FactoryInjectionToken\n * @returns The normalized InjectionTokenType\n */\n normalizeToken(token: AnyInjectableType): InjectionTokenType {\n if (typeof token === 'function') {\n return getInjectableToken(token)\n }\n return token as InjectionTokenType\n }\n\n /**\n * Gets the underlying \"real\" token from wrapped tokens.\n * For BoundInjectionToken and FactoryInjectionToken, returns the wrapped token.\n * For other tokens, returns the token itself.\n *\n * @param token The token to unwrap\n * @returns The underlying InjectionToken\n */\n getRealToken<T = unknown>(token: InjectionTokenType): InjectionToken<T> {\n if (\n token instanceof BoundInjectionToken ||\n token instanceof FactoryInjectionToken\n ) {\n return token.token as InjectionToken<T>\n }\n return token as InjectionToken<T>\n }\n\n /**\n * Convenience method that normalizes a token and then gets the real token.\n * Useful for checking registry entries where you need the actual registered token.\n *\n * @param token Any injectable type\n * @returns The underlying InjectionToken\n */\n getRegistryToken<T = unknown>(token: AnyInjectableType): InjectionToken<T> {\n return this.getRealToken(this.normalizeToken(token))\n }\n\n // ============================================================================\n // TOKEN VALIDATION\n // ============================================================================\n\n /**\n * Validates and resolves token arguments, handling factory token resolution and validation.\n */\n validateAndResolveTokenArgs(\n token: AnyInjectableType,\n args?: any,\n ): [\n DIError | undefined,\n { actualToken: InjectionTokenType; validatedArgs?: any },\n ] {\n let actualToken = token as InjectionToken<any, any>\n if (typeof token === 'function') {\n actualToken = getInjectableToken(token)\n }\n let realArgs = args\n if (actualToken instanceof BoundInjectionToken) {\n realArgs = actualToken.value\n } else if (actualToken instanceof FactoryInjectionToken) {\n if (actualToken.resolved) {\n realArgs = actualToken.value\n } else {\n return [DIError.factoryTokenNotResolved(token.name), { actualToken }]\n }\n }\n if (!actualToken.schema) {\n return [undefined, { actualToken, validatedArgs: realArgs }]\n }\n const validatedArgs = actualToken.schema?.safeParse(realArgs)\n if (validatedArgs && !validatedArgs.success) {\n this.logger?.error(\n `[TokenProcessor]#validateAndResolveTokenArgs(): Error validating args for ${actualToken.name.toString()}`,\n validatedArgs.error,\n )\n return [DIError.unknown(validatedArgs.error), { actualToken }]\n }\n return [undefined, { actualToken, validatedArgs: validatedArgs?.data }]\n }\n\n /**\n * Generates a unique instance name based on token and arguments.\n */\n generateInstanceName(token: InjectionTokenType, args: any): string {\n if (!args) {\n return token.toString()\n }\n\n const formattedArgs = Object.entries(args)\n .sort(([keyA], [keyB]) => keyA.localeCompare(keyB))\n .map(([key, value]) => `${key}=${this.formatArgValue(value)}`)\n .join(',')\n\n return `${token.toString()}:${formattedArgs.replaceAll(/\"/g, '').replaceAll(/:/g, '=')}`\n }\n\n /**\n * Formats a single argument value for instance name generation.\n */\n formatArgValue(value: any): string {\n if (typeof value === 'function') {\n return `fn_${value.name}(${value.length})`\n }\n if (typeof value === 'symbol') {\n return value.toString()\n }\n return JSON.stringify(value).slice(0, 40)\n }\n\n /**\n * Creates a factory context for dependency injection during service instantiation.\n * @param container The container instance (Container or ScopedContainer) for dependency resolution\n * @param onDependencyResolved Callback when a dependency is resolved, receives the instance name\n */\n createFactoryContext(\n container: IContainer,\n onDependencyResolved?: (instanceName: string) => void,\n ): FactoryContext & {\n getDestroyListeners: () => (() => void)[]\n deps: Set<string>\n } {\n const destroyListeners = new Set<() => void>()\n const deps = new Set<string>()\n\n function addDestroyListener(listener: () => void) {\n destroyListeners.add(listener)\n }\n\n function getDestroyListeners() {\n return Array.from(destroyListeners)\n }\n\n const self = this\n\n return {\n // @ts-expect-error This is correct type\n async inject(token, args) {\n // Get the instance name for dependency tracking\n const actualToken =\n typeof token === 'function' ? getInjectableToken(token) : token\n const instanceName = self.generateInstanceName(actualToken, args)\n deps.add(instanceName)\n\n if (onDependencyResolved) {\n onDependencyResolved(instanceName)\n }\n\n // Use the container's get method for resolution\n return container.get(token, args)\n },\n addDestroyListener,\n getDestroyListeners,\n container,\n deps,\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-empty-object-type */\nimport type { z, ZodObject, ZodOptional } from 'zod/v4'\n\nimport type {\n AnyInjectableType,\n InjectionTokenSchemaType,\n} from '../../token/injection-token.mjs'\nimport type { IContainer } from '../../interfaces/container.interface.mjs'\nimport type { Registry } from '../../token/registry.mjs'\nimport type { ScopedContainer } from '../../container/scoped-container.mjs'\nimport type { ClearAllOptions } from './invalidator.mjs'\nimport type { Injectors } from '../../utils/index.mjs'\n\nimport { defaultInjectors } from '../../injectors.mjs'\nimport { InstanceResolver } from './instance-resolver.mjs'\nimport { globalRegistry } from '../../token/registry.mjs'\nimport { Instantiator } from './instantiator.mjs'\nimport { Invalidator } from './invalidator.mjs'\nimport { LifecycleEventBus } from '../lifecycle/lifecycle-event-bus.mjs'\nimport { HolderManager } from '../holder/holder-manager.mjs'\nimport { TokenProcessor } from './token-processor.mjs'\n\n/**\n * Core DI engine that coordinates service instantiation, resolution, and lifecycle.\n *\n * Acts as the central orchestrator for dependency injection operations,\n * delegating to specialized components (InstanceResolver, Instantiator, Invalidator)\n * for specific tasks.\n */\nexport class ServiceLocator {\n private readonly eventBus: LifecycleEventBus\n private readonly manager: HolderManager\n private readonly instantiator: Instantiator\n private readonly tokenProcessor: TokenProcessor\n private readonly invalidator: Invalidator\n private readonly instanceResolver: InstanceResolver\n\n constructor(\n private readonly registry: Registry = globalRegistry,\n private readonly logger: Console | null = null,\n private readonly injectors: Injectors = defaultInjectors,\n ) {\n this.eventBus = new LifecycleEventBus(logger)\n this.manager = new HolderManager(logger)\n this.instantiator = new Instantiator(injectors)\n this.tokenProcessor = new TokenProcessor(logger)\n this.invalidator = new Invalidator(\n this.manager,\n this.eventBus,\n logger,\n )\n this.instanceResolver = new InstanceResolver(\n this.registry,\n this.manager,\n this.instantiator,\n this.tokenProcessor,\n logger,\n this,\n )\n }\n\n // ============================================================================\n // PUBLIC METHODS\n // ============================================================================\n\n getEventBus() {\n return this.eventBus\n }\n\n getManager() {\n return this.manager\n }\n\n getInvalidator() {\n return this.invalidator\n }\n\n getTokenProcessor() {\n return this.tokenProcessor\n }\n\n public getInstanceIdentifier(token: AnyInjectableType, args?: any): string {\n const [err, { actualToken, validatedArgs }] =\n this.tokenProcessor.validateAndResolveTokenArgs(token, args)\n if (err) {\n throw err\n }\n return this.tokenProcessor.generateInstanceName(actualToken, validatedArgs)\n }\n\n /**\n * Gets or creates an instance for the given token.\n * @param token The injection token\n * @param args Optional arguments\n * @param contextContainer The container to use for creating FactoryContext\n */\n public async getInstance(\n token: AnyInjectableType,\n args: any,\n contextContainer: IContainer,\n ) {\n const [err, data] = await this.instanceResolver.resolveInstance(\n token,\n args,\n contextContainer,\n )\n if (err) {\n return [err]\n }\n\n return [undefined, data]\n }\n\n /**\n * Gets or throws an instance for the given token.\n * @param token The injection token\n * @param args Optional arguments\n * @param contextContainer The container to use for creating FactoryContext\n */\n public async getOrThrowInstance<Instance>(\n token: AnyInjectableType,\n args: any,\n contextContainer: IContainer,\n ): Promise<Instance> {\n const [error, instance] = await this.getInstance(token, args, contextContainer)\n if (error) {\n throw error\n }\n return instance\n }\n\n /**\n * Resolves a request-scoped service for a ScopedContainer.\n * The service will be stored in the ScopedContainer's request context.\n *\n * @param token The injection token\n * @param args Optional arguments\n * @param scopedContainer The ScopedContainer that owns the request context\n */\n public async resolveRequestScoped(\n token: AnyInjectableType,\n args: any,\n scopedContainer: ScopedContainer,\n ): Promise<any> {\n const [err, data] = await this.instanceResolver.resolveRequestScopedInstance(\n token,\n args,\n scopedContainer,\n )\n if (err) {\n throw err\n }\n return data\n }\n\n public getSyncInstance<\n Instance,\n Schema extends InjectionTokenSchemaType | undefined,\n >(\n token: AnyInjectableType,\n args: Schema extends ZodObject\n ? z.input<Schema>\n : Schema extends ZodOptional<ZodObject>\n ? z.input<Schema> | undefined\n : undefined,\n contextContainer: IContainer,\n ): Instance | null {\n return this.instanceResolver.getSyncInstance(token, args as any, contextContainer)\n }\n\n invalidate(service: string, round = 1): Promise<any> {\n return this.invalidator.invalidate(service, round)\n }\n\n /**\n * Gracefully clears all services in the ServiceLocator using invalidation logic.\n * This method respects service dependencies and ensures proper cleanup order.\n * Services that depend on others will be invalidated first, then their dependencies.\n *\n * @param options Optional configuration for the clearing process\n * @returns Promise that resolves when all services have been cleared\n */\n async clearAll(options: ClearAllOptions = {}): Promise<void> {\n return this.invalidator.clearAll(options)\n }\n\n /**\n * Waits for all services to settle (either created, destroyed, or error state).\n */\n async ready(): Promise<void> {\n return this.invalidator.ready()\n }\n\n /**\n * Helper method for InstanceResolver to generate instance names.\n * This is needed for the factory context creation.\n */\n generateInstanceName(token: any, args: any): string {\n return this.tokenProcessor.generateInstanceName(token, args)\n }\n}\n","import type { z, ZodType } from 'zod/v4'\n\nimport type {\n ClassType,\n ClassTypeWithArgument,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '../token/injection-token.mjs'\nimport type { IContainer } from '../interfaces/container.interface.mjs'\nimport type { Factorable } from '../interfaces/factory.interface.mjs'\nimport type { Registry } from '../token/registry.mjs'\nimport type { InstanceHolder } from '../internal/holder/instance-holder.mjs'\nimport type { Injectors } from '../utils/index.mjs'\nimport type { Join, UnionToArray } from '../utils/types.mjs'\n\nimport { Injectable } from '../decorators/injectable.decorator.mjs'\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\nimport { DIError } from '../errors/index.mjs'\nimport {\n BoundInjectionToken,\n FactoryInjectionToken,\n} from '../token/injection-token.mjs'\nimport { defaultInjectors } from '../injectors.mjs'\nimport { globalRegistry } from '../token/registry.mjs'\nimport { ScopedContainer } from './scoped-container.mjs'\nimport { ServiceLocator } from '../internal/core/service-locator.mjs'\nimport { getInjectableToken } from '../utils/get-injectable-token.mjs'\n\n/**\n * Main dependency injection container.\n *\n * Provides a simplified public API for dependency injection, wrapping\n * a ServiceLocator instance. Handles singleton and transient services directly,\n * while request-scoped services require using beginRequest() to create a ScopedContainer.\n */\n@Injectable()\nexport class Container implements IContainer {\n private readonly serviceLocator: ServiceLocator\n private readonly activeRequestIds = new Set<string>()\n\n constructor(\n protected readonly registry: Registry = globalRegistry,\n protected readonly logger: Console | null = null,\n protected readonly injectors: Injectors = defaultInjectors,\n ) {\n this.serviceLocator = new ServiceLocator(registry, logger, injectors)\n this.registerSelf()\n }\n\n private registerSelf() {\n const token = getInjectableToken(Container)\n const instanceName = this.serviceLocator.getInstanceIdentifier(token)\n this.serviceLocator\n .getManager()\n .storeCreatedHolder(\n instanceName,\n this,\n InjectableType.Class,\n InjectableScope.Singleton,\n )\n }\n\n /**\n * Gets an instance from the container.\n * This method has the same type signature as the inject method from get-injectors.mts\n *\n * NOTE: Request-scoped services cannot be resolved directly from Container.\n * Use beginRequest() to create a ScopedContainer for request-scoped services.\n */\n // #1 Simple class\n get<T extends ClassType>(\n token: T,\n ): InstanceType<T> extends Factorable<infer R>\n ? Promise<R>\n : Promise<InstanceType<T>>\n // #1.1 Simple class with args\n get<T extends ClassTypeWithArgument<R>, R>(\n token: T,\n args: R,\n ): Promise<InstanceType<T>>\n\n // #2 Token with required Schema\n get<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n ): Promise<T>\n // #3 Token with optional Schema\n get<T, S extends InjectionTokenSchemaType, R extends boolean>(\n token: InjectionToken<T, S, R>,\n ): R extends false\n ? Promise<T>\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<\n UnionToArray<keyof Type>,\n ', '\n >}`\n : 'Error: Your token requires args'\n // #4 Token with no Schema\n get<T>(token: InjectionToken<T, undefined>): Promise<T>\n get<T>(token: BoundInjectionToken<T, any>): Promise<T>\n get<T>(token: FactoryInjectionToken<T, any>): Promise<T>\n\n async get(\n token:\n | ClassType\n | InjectionToken<any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args?: unknown,\n ) {\n // Check if this is a request-scoped service\n // Use TokenProcessor for consistent token normalization\n const tokenProcessor = this.serviceLocator.getTokenProcessor()\n const realToken = tokenProcessor.getRegistryToken(token)\n\n if (this.registry.has(realToken)) {\n const record = this.registry.get(realToken)\n if (record.scope === InjectableScope.Request) {\n throw DIError.unknown(\n `Cannot resolve request-scoped service \"${String(realToken.name)}\" from Container. ` +\n `Use beginRequest() to create a ScopedContainer for request-scoped services.`,\n )\n }\n }\n\n return this.serviceLocator.getOrThrowInstance(token, args as any, this)\n }\n\n /**\n * Gets an instance with a specific container context.\n * Used by ScopedContainer to delegate singleton/transient resolution\n * while maintaining the correct container context for nested inject() calls.\n *\n * @internal\n */\n async getWithContext(\n token:\n | ClassType\n | InjectionToken<any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args: unknown,\n contextContainer: IContainer,\n ): Promise<any> {\n return this.serviceLocator.getOrThrowInstance(\n token,\n args as any,\n contextContainer,\n )\n }\n\n /**\n * Resolves a request-scoped service for a ScopedContainer.\n * The service will be stored in the ScopedContainer's request context.\n *\n * @internal\n */\n async resolveForRequest(\n token:\n | ClassType\n | InjectionToken<any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args: unknown,\n scopedContainer: ScopedContainer,\n ): Promise<any> {\n return this.serviceLocator.resolveRequestScoped(\n token,\n args as any,\n scopedContainer,\n )\n }\n\n /**\n * Gets the underlying ServiceLocator instance for advanced usage\n */\n getServiceLocator(): ServiceLocator {\n return this.serviceLocator\n }\n\n /**\n * Gets the registry\n */\n getRegistry(): Registry {\n return this.registry\n }\n\n /**\n * Invalidates a service and its dependencies\n */\n async invalidate(service: unknown): Promise<void> {\n const holder = this.getHolderByInstance(service)\n if (holder) {\n await this.serviceLocator.invalidate(holder.name)\n }\n }\n\n /**\n * Gets a service holder by instance (reverse lookup)\n */\n private getHolderByInstance(\n instance: unknown,\n ): InstanceHolder | null {\n const holderMap = Array.from(\n this.serviceLocator\n .getManager()\n .filter((holder) => holder.instance === instance)\n .values(),\n )\n\n return holderMap.length > 0 ? holderMap[0] : null\n }\n\n /**\n * Checks if a service is registered in the container\n */\n isRegistered(token: any): boolean {\n try {\n return this.serviceLocator.getInstanceIdentifier(token) !== null\n } catch {\n return false\n }\n }\n\n /**\n * Disposes the container and cleans up all resources\n */\n async dispose(): Promise<void> {\n await this.serviceLocator.clearAll()\n }\n\n /**\n * Waits for all pending operations to complete\n */\n async ready(): Promise<void> {\n await this.serviceLocator.ready()\n }\n\n /**\n * @internal\n * Attempts to get an instance synchronously if it already exists.\n * Returns null if the instance doesn't exist or is not ready.\n */\n tryGetSync<T>(token: any, args?: any): T | null {\n return this.serviceLocator.getSyncInstance(token, args, this)\n }\n\n // ============================================================================\n // REQUEST CONTEXT MANAGEMENT\n // ============================================================================\n\n /**\n * Begins a new request context and returns a ScopedContainer.\n *\n * The ScopedContainer provides isolated request-scoped service resolution\n * while delegating singleton and transient services to this Container.\n *\n * @param requestId Unique identifier for this request\n * @param metadata Optional metadata for the request\n * @param priority Priority for resolution (higher = more priority)\n * @returns A ScopedContainer for this request\n */\n beginRequest(\n requestId: string,\n metadata?: Record<string, any>,\n priority: number = 100,\n ): ScopedContainer {\n if (this.activeRequestIds.has(requestId)) {\n throw DIError.unknown(\n `Request context \"${requestId}\" already exists. Use a unique request ID.`,\n )\n }\n\n this.activeRequestIds.add(requestId)\n\n this.logger?.log(`[Container] Started request context: ${requestId}`)\n\n return new ScopedContainer(\n this,\n this.registry,\n requestId,\n metadata,\n priority,\n )\n }\n\n /**\n * Removes a request ID from the active set.\n * Called by ScopedContainer when the request ends.\n *\n * @internal\n */\n removeActiveRequest(requestId: string): void {\n this.activeRequestIds.delete(requestId)\n this.logger?.log(`[Container] Ended request context: ${requestId}`)\n }\n\n /**\n * Gets the set of active request IDs.\n */\n getActiveRequestIds(): ReadonlySet<string> {\n return this.activeRequestIds\n }\n\n /**\n * Checks if a request ID is currently active.\n */\n hasActiveRequest(requestId: string): boolean {\n return this.activeRequestIds.has(requestId)\n }\n\n /**\n * Clears all instances and bindings from the container.\n * This is useful for testing or resetting the container state.\n */\n clear(): Promise<void> {\n return this.serviceLocator.clearAll()\n }\n}\n","import type {\n ClassTypeWithInstance,\n InjectionTokenSchemaType,\n} from '../token/injection-token.mjs'\nimport type { Factorable, FactorableWithArgs } from '../interfaces/index.mjs'\nimport type { Registry } from '../token/registry.mjs'\n\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\nimport { InjectionToken } from '../token/injection-token.mjs'\nimport { globalRegistry } from '../token/registry.mjs'\nimport { InjectableTokenMeta } from '../symbols/index.mjs'\n\nexport interface FactoryOptions {\n scope?: InjectableScope\n token?: InjectionToken<any, any>\n registry?: Registry\n}\n\n// #1 Factory without arguments\nexport function Factory<R>(options?: {\n scope?: InjectableScope\n registry?: Registry\n}): <T extends ClassTypeWithInstance<Factorable<R>>>(\n target: T,\n context?: ClassDecoratorContext,\n) => T\n\n// #2 Factory with typed token\nexport function Factory<R, S>(options: {\n scope?: InjectableScope\n token: InjectionToken<R, S>\n registry?: Registry\n}): R extends undefined // #2.1 Check that token has a type\n ? never // #2.1.1 Token must have a type\n : S extends InjectionTokenSchemaType // #2.2 Check that schema is an object or a record\n ? <T extends ClassTypeWithInstance<FactorableWithArgs<R, S>>>( // #2.2.1 Token have a schema\n target: T,\n context?: ClassDecoratorContext,\n ) => T\n : S extends undefined // #2.3 For a factory without schema\n ? <T extends ClassTypeWithInstance<Factorable<R>>>( // #2.3.1 Token without a schema\n target: T,\n context?: ClassDecoratorContext,\n ) => T\n : never // #2.4 Cannot use a token without a type and schema\n\nexport function Factory({\n scope = InjectableScope.Singleton,\n token,\n registry = globalRegistry,\n}: FactoryOptions = {}) {\n return <\n T extends ClassTypeWithInstance<\n Factorable<any> | FactorableWithArgs<any, any>\n >,\n >(\n target: T,\n context?: ClassDecoratorContext,\n ): T => {\n if (\n (context && context.kind !== 'class') ||\n (target instanceof Function && !context)\n ) {\n throw new Error(\n '[ServiceLocator] @Factory decorator can only be used on classes.',\n )\n }\n\n let injectableToken: InjectionToken<any, any> =\n token ?? InjectionToken.create(target)\n\n registry.set(injectableToken, scope, target, InjectableType.Factory)\n\n // @ts-expect-error\n target[InjectableTokenMeta] = injectableToken\n\n return target\n }\n}\n","/* eslint-disable @typescript-eslint/no-non-null-assertion */\n/* eslint-disable @typescript-eslint/no-empty-object-type */\n/* eslint-disable @typescript-eslint/no-unsafe-function-type */\n\nimport { Injectable, InjectableScope } from './index.mjs'\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport type EventsConfig = {\n [event: string]: any[]\n}\nexport type EventsNames<Events extends EventsConfig> = Exclude<\n keyof Events,\n symbol | number\n>\nexport type EventsArgs<\n Events extends EventsConfig,\n Name extends EventsNames<Events>,\n> = Events[Name] extends any[] ? Events[Name] : []\n\nexport type ChannelEmitter<\n Events extends EventsConfig,\n Ns extends string,\n E extends EventsNames<Events>,\n> = {\n emit<Args extends EventsArgs<Events, E>>(\n ns: Ns,\n event: E,\n ...args: Args\n ): Promise<any>\n}\n\nexport interface EventEmitterInterface<Events extends EventsConfig> {\n on<E extends EventsNames<Events>, Args extends EventsArgs<Events, E>>(\n event: E,\n listener: (...args: Args) => void | Promise<void>,\n ): () => void\n emit<E extends EventsNames<Events>, Args extends EventsArgs<Events, E>>(\n event: E,\n ...args: Args\n ): void | Promise<void>\n}\n\n@Injectable({ scope: InjectableScope.Transient })\nexport class EventEmitter<Events extends EventsConfig = {}>\n implements EventEmitterInterface<Events>\n{\n private listeners: Map<EventsNames<Events>, Set<Function>> = new Map()\n\n on<E extends EventsNames<Events>, Args extends EventsArgs<Events, E>>(\n event: E,\n listener: (...args: Args) => void | Promise<void>,\n ) {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n\n this.listeners.get(event)!.add(listener)\n\n return () => {\n this.off(event, listener)\n }\n }\n\n off<E extends EventsNames<Events>, Args extends EventsArgs<Events, E>>(\n event: E,\n listener: (...args: Args) => void | Promise<void>,\n ) {\n if (!this.listeners.has(event)) {\n return\n }\n\n this.listeners.get(event)!.delete(listener)\n if (this.listeners.get(event)!.size === 0) {\n this.listeners.delete(event)\n }\n }\n\n once<E extends EventsNames<Events>, Args extends EventsArgs<Events, E>>(\n event: E,\n listener: (...args: Args) => void | Promise<void>,\n ) {\n const off = this.on(event, (...args) => {\n off()\n // @ts-expect-error - This is a valid call\n listener(...args)\n })\n\n return off\n }\n\n async emit<E extends EventsNames<Events>, Args extends EventsArgs<Events, E>>(\n event: E,\n ...args: Args\n ): Promise<any> {\n if (!this.listeners.has(event)) {\n return\n }\n\n return Promise.all(\n Array.from(this.listeners.get(event)!).map((listener) =>\n listener(...args),\n ),\n )\n }\n}\n","import type { ClassType, InjectionToken } from '../token/injection-token.mjs'\nimport type { Registry } from '../token/registry.mjs'\nimport type { Injectors } from '../utils/index.mjs'\n\nimport { Container } from '../container/container.mjs'\nimport { Injectable } from '../decorators/injectable.decorator.mjs'\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\nimport { globalRegistry } from '../token/registry.mjs'\nimport { getInjectableToken } from '../utils/index.mjs'\n\n/**\n * A binding builder for the TestContainer that allows chaining binding operations.\n */\nexport class TestBindingBuilder<T> {\n constructor(\n private readonly container: TestContainer,\n private readonly token: InjectionToken<T, any>,\n ) {}\n\n /**\n * Binds the token to a specific value.\n * This is useful for testing with mock values or constants.\n * @param value The value to bind to the token\n */\n toValue(value: T): TestContainer {\n const instanceName = this.container\n .getServiceLocator()\n .getInstanceIdentifier(this.token)\n this.container\n .getServiceLocator()\n .getManager()\n .storeCreatedHolder(\n instanceName,\n value,\n InjectableType.Class,\n InjectableScope.Singleton,\n )\n return this.container\n }\n\n /**\n * Binds the token to a class constructor.\n * @param target The class constructor to bind to\n */\n toClass(target: ClassType): TestContainer {\n this.container['registry'].set(\n this.token,\n InjectableScope.Singleton,\n target,\n InjectableType.Class,\n )\n return this.container\n }\n}\n\n/**\n * TestContainer extends the base Container with additional methods useful for testing.\n * It provides a simplified API for binding values and classes during test setup.\n */\n@Injectable()\nexport class TestContainer extends Container {\n constructor(\n registry: Registry = globalRegistry,\n logger: Console | null = null,\n injectors: Injectors = undefined as any,\n ) {\n super(registry, logger, injectors)\n }\n\n /**\n * Creates a binding builder for the given token.\n * This allows chaining binding operations like bind(Token).toValue(value).\n * @param token The injection token to bind\n * @returns A TestBindingBuilder for chaining binding operations\n */\n bind<T>(token: ClassType): TestBindingBuilder<T>\n bind<T>(token: InjectionToken<T, any>): TestBindingBuilder<T>\n bind(token: any): TestBindingBuilder<any> {\n let realToken = token\n if (typeof token === 'function') {\n realToken = getInjectableToken(token)\n }\n return new TestBindingBuilder(this, realToken)\n }\n\n /**\n * Binds a value directly to a token.\n * This is a convenience method equivalent to bind(token).toValue(value).\n * @param token The injection token to bind\n * @param value The value to bind to the token\n * @returns The TestContainer instance for chaining\n */\n bindValue<T>(token: ClassType, value: T): TestContainer\n bindValue<T>(token: InjectionToken<T, any>, value: T): TestContainer\n bindValue(token: any, value: any): TestContainer {\n return this.bind(token).toValue(value)\n }\n\n /**\n * Binds a class to a token.\n * This is a convenience method equivalent to bind(token).toClass(target).\n * @param token The injection token to bind\n * @param target The class constructor to bind to\n * @returns The TestContainer instance for chaining\n */\n bindClass(token: ClassType, target: ClassType): TestContainer\n bindClass<T>(token: InjectionToken<T, any>, target: ClassType): TestContainer\n bindClass(token: any, target: any): TestContainer {\n return this.bind(token).toClass(target)\n }\n\n /**\n * Creates a new TestContainer instance with the same configuration.\n * This is useful for creating isolated test containers.\n * @returns A new TestContainer instance\n */\n createChild(): TestContainer {\n return new TestContainer(this.registry, this.logger, this.injectors)\n }\n}\n","/**\n * Browser-specific entry point for @navios/di.\n *\n * This entry point forces the use of SyncLocalStorage instead of\n * Node's AsyncLocalStorage, making it safe for browser environments.\n *\n * The browser build is automatically selected by bundlers that respect\n * the \"browser\" condition in package.json exports.\n */\n\n// Force sync mode before any other imports initialize the storage\nimport { __testing__ } from './internal/context/async-local-storage.mjs'\n__testing__.forceSyncMode()\n\n// Re-export everything from the main entry\nexport * from './index.mjs'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["InjectionToken","id","globalThis","crypto","randomUUID","formattedName","name","schema","create","bound","token","value","BoundInjectionToken","factory","FactoryInjectionToken","refineType","toString","className","resolved","resolve","ctx","Registry","factories","Map","parent","has","token","id","get","factory","Error","toString","set","scope","target","type","originalToken","delete","updateScope","globalRegistry","InjectableScope","InjectableType","InjectionToken","globalRegistry","InjectableTokenMeta","Injectable","scope","Singleton","token","schema","registry","target","context","kind","Function","Error","injectableToken","create","set","Class","code: DIErrorCode","message: string","createAsyncLocalStorage","resolutionContext","getResolutionContext","withResolutionContext","waiterHolder","getHolder","fn","run","getCurrentResolutionContext","getStore","withoutResolutionContext","undefined","InjectableTokenMeta","withoutResolutionContext","getInjectors","currentFactoryContext","provideFactoryContext","context","original","getFactoryContext","Error","promiseCollector","injectState","getRequest","token","args","skipCycleTracking","isFrozen","idx","currentIndex","request","requests","toString","result","error","doInject","inject","then","r","catch","e","promise","push","asyncInject","realToken","wrapSyncInit","cb","previousState","promises","originalPromiseCollector","originalInjectState","newInjectState","instance","container","tryGetSync","Proxy","get","optional","injectors","InjectableTokenMeta","getInjectableToken","target","token","Error","name","asyncInject: Injectors['asyncInject']","inject: Injectors['inject']","optional: Injectors['optional']","wrapSyncInit: Injectors['wrapSyncInit']","provideFactoryContext: Injectors['provideFactoryContext']","isProduction","process","env","NODE_ENV","CircularDetector","detectCycle","waiterName","targetName","getHolder","visited","Set","queue","name","path","length","currentName","shift","has","add","holder","waitingForName","waitingFor","push","formatCycle","cycle","join","DIError","CircularDetector","InstanceStatus","BaseHolderManager","_holders","logger","Map","holders","delete","name","filter","predicate","key","value","clear","size","createCreatingHolder","type","scope","deps","Set","deferred","Promise","withResolvers","holder","status","Creating","instance","creationPromise","promise","destroyPromise","destroyListeners","createdAt","Date","now","waitingFor","createCreatedHolder","Created","getAllNames","Array","from","keys","getAllHolders","values","isEmpty","waitForHolderReady","waiterHolder","getHolder","cycle","detectCycle","circularDependency","add","Destroying","instanceDestroying","Error","undefined","instanceNotFound","BaseHolderManager","InjectableScope","InjectableType","InjectionToken","DefaultRequestContext","metadata","Map","createdAt","Date","now","requestId","priority","initialMetadata","Object","entries","forEach","key","value","set","holders","_holders","get","name","holder","has","addInstance","instanceName","instance","toString","createdHolder","createCreatedHolder","Class","Singleton","Set","Error","clear","getMetadata","setMetadata","createRequestContext","contextHolder: RequestContext","holderManager: BaseHolderManager","names: string[]","dependents: string[]","BaseHolderManager","InjectableScope","DIError","DefaultRequestContext","RequestStorage","InstanceStatus","ScopedContainer","requestContextHolder","holderStorage","disposed","parent","registry","requestId","metadata","priority","getServiceLocator","getManager","getRequestContextHolder","getHolderStorage","getRequestId","getParent","getMetadata","key","setMetadata","value","addInstance","token","instance","get","args","unknown","tokenProcessor","getTokenProcessor","actualToken","normalizeToken","isRequestScoped","resolveRequestScoped","getWithContext","invalidate","service","holder","findByInstance","getInvalidator","invalidateWithStorage","name","emitEvents","isRegistered","dispose","endRequest","clearAllWithStorage","waitForSettlement","maxRounds","clear","removeActiveRequest","ready","tryGetSync","serviceLocator","instanceName","getInstanceIdentifier","status","Created","realToken","getRealToken","has","record","scope","Request","existingHolder","Error","delete","error","readyHolder","waitForHolderReady","resolveForRequest","storeRequestInstance","getRequestInstance","getPrefixedEventName","manager: HolderManager","dependents: string[]","InjectableScope","DIError","DIErrorCode","BoundInjectionToken","FactoryInjectionToken","getCurrentResolutionContext","withResolutionContext","BaseHolderManager","InstanceStatus","SingletonStorage","InstanceResolver","singletonStorage","registry","manager","instantiator","tokenProcessor","logger","serviceLocator","resolveInstance","token","args","contextContainer","resolveWithStorage","resolveRequestScopedInstance","scopedContainer","getHolderStorage","storage","err","data","resolveTokenAndPrepareInstanceName","instanceName","validatedArgs","realToken","getResult","get","error","holder","readyResult","waitForInstanceReady","undefined","instance","handledResult","handleStorageError","createError","createAndStoreInstance","code","InstanceDestroying","log","destroyPromise","newResult","delete","has","factoryNotFound","name","toString","ctx","createFactoryContext","record","scope","type","Transient","createTransientInstance","deferred","createCreatingHolder","deps","set","getHolder","storageResult","storageHolder","managerHolder","instantiateService","then","result","length","handleInstantiationResult","catch","handleInstantiationError","tempHolder","status","Creating","creationPromise","destroyListeners","createdAt","Date","now","waitingFor","Set","Created","getDestroyListeners","getSyncInstance","actualToken","validateAndResolveTokenArgs","generateInstanceName","requestHolder","getRequestInstance","UnknownError","FactoryTokenNotResolved","resolve","waitForHolderReady","waiterHolder","handleInstantiationSuccess","size","forEach","dependency","push","getEventBus","on","getInvalidator","invalidate","prefixedDependency","getPrefixedEventName","Error","Singleton","reject","InjectableType","DIError","Instantiator","injectors","instantiateService","ctx","record","args","undefined","type","Class","instantiateClass","Factory","instantiateFactory","unknown","error","String","tryLoad","wrapSyncInit","original","provideFactoryContext","result","target","instance","promises","injectState","length","results","Promise","allSettled","some","status","name","newRes","console","onServiceInit","addDestroyListener","onServiceDestroy","builder","create","InstanceStatus","SingletonStorage","Invalidator","storage","manager","eventBus","logger","invalidate","service","round","invalidateWithStorage","options","cascade","_invalidating","Set","has","log","result","get","add","optionsWithTracking","dependents","findDependents","dependentName","holder","invalidateHolderWithStorage","clearAll","clearAllWithStorage","maxRounds","waitForSettlement","readyWithStorage","allServiceNames","getAllNames","length","join","clearServicesWithDependencyAwarenessForStorage","ready","holders","forEach","_","push","Promise","all","map","waitForHolderToSettle","key","emitEvents","onInvalidated","invalidateHolderByStatus","context","onCreationError","error","onRecursiveInvalidate","onDestroy","destroyHolderWithStorage","status","Destroying","destroyPromise","Creating","creationPromise","destroyListeners","listener","then","deps","clear","delete","emitInstanceEvent","Created","Error","serviceNames","clearedServices","size","servicesToClearThisRound","findServicesReadyForClearingInStorage","remainingServices","filter","name","warn","forceClearServicesInStorage","clearPromises","serviceName","hasUnclearedDependencies","Array","from","some","dep","promises","event","resolve","emit","LifecycleEventBus","listeners","Map","logger","on","ns","event","listener","debug","has","set","nsEvents","get","Set","add","delete","size","emit","key","events","res","Promise","allSettled","map","then","results","filter","result","status","warn","reason","length","reject","DIError","DIErrorCode","BaseHolderManager","InstanceStatus","HolderManager","logger","get","name","holder","_holders","status","Destroying","log","instanceDestroying","Error","instance","undefined","instanceNotFound","set","has","error","code","InstanceDestroying","storeCreatedHolder","type","scope","deps","Set","createCreatedHolder","DIError","BoundInjectionToken","FactoryInjectionToken","getInjectableToken","TokenProcessor","logger","normalizeToken","token","getRealToken","getRegistryToken","validateAndResolveTokenArgs","args","actualToken","realArgs","value","resolved","factoryTokenNotResolved","name","schema","undefined","validatedArgs","safeParse","success","error","toString","unknown","data","generateInstanceName","formattedArgs","Object","entries","sort","keyA","keyB","localeCompare","map","key","formatArgValue","join","replaceAll","length","JSON","stringify","slice","createFactoryContext","container","onDependencyResolved","destroyListeners","Set","deps","addDestroyListener","listener","add","getDestroyListeners","Array","from","self","inject","instanceName","get","defaultInjectors","InstanceResolver","globalRegistry","Instantiator","Invalidator","LifecycleEventBus","HolderManager","TokenProcessor","ServiceLocator","eventBus","manager","instantiator","tokenProcessor","invalidator","instanceResolver","registry","logger","injectors","getEventBus","getManager","getInvalidator","getTokenProcessor","getInstanceIdentifier","token","args","err","actualToken","validatedArgs","validateAndResolveTokenArgs","generateInstanceName","getInstance","contextContainer","data","resolveInstance","undefined","getOrThrowInstance","error","instance","resolveRequestScoped","scopedContainer","resolveRequestScopedInstance","getSyncInstance","invalidate","service","round","clearAll","options","ready","Injectable","InjectableScope","InjectableType","DIError","defaultInjectors","globalRegistry","ScopedContainer","ServiceLocator","getInjectableToken","Container","registry","logger","injectors","serviceLocator","registerSelf","activeRequestIds","Set","token","instanceName","getInstanceIdentifier","getManager","storeCreatedHolder","Class","Singleton","get","args","tokenProcessor","getTokenProcessor","realToken","getRegistryToken","has","record","scope","Request","unknown","String","name","getOrThrowInstance","getWithContext","contextContainer","resolveForRequest","scopedContainer","resolveRequestScoped","getServiceLocator","getRegistry","invalidate","service","holder","getHolderByInstance","instance","holderMap","Array","from","filter","values","length","isRegistered","dispose","clearAll","ready","tryGetSync","getSyncInstance","beginRequest","requestId","metadata","priority","add","log","removeActiveRequest","delete","getActiveRequestIds","hasActiveRequest","clear","InjectableScope","InjectableType","InjectionToken","globalRegistry","InjectableTokenMeta","Factory","scope","Singleton","token","registry","target","context","kind","Function","Error","injectableToken","create","set","Injectable","InjectableScope","scope","Transient","EventEmitter","listeners","Map","on","event","listener","has","set","Set","get","add","off","delete","size","once","args","emit","Promise","all","Array","from","map"],"sources":["../../src/enums/injectable-scope.enum.mts","../../src/enums/injectable-type.enum.mts","../../src/token/injection-token.mts","../../src/token/registry.mts","../../src/symbols/injectable-token.mts","../../src/decorators/injectable.decorator.mts","../../src/errors/di-error.mts","../../src/internal/context/sync-local-storage.mts","../../src/internal/context/async-local-storage.browser.mts","../../src/internal/context/resolution-context.mts","../../src/utils/get-injectors.mts","../../src/utils/get-injectable-token.mts","../../src/injectors.mts","../../src/internal/lifecycle/circular-detector.mts","../../src/internal/holder/instance-holder.mts","../../src/internal/holder/base-holder-manager.mts","../../src/internal/context/request-context.mts","../../src/internal/holder/request-storage.mts","../../src/container/scoped-container.mts","../../src/internal/holder/singleton-storage.mts","../../src/internal/core/instance-resolver.mts","../../src/internal/core/instantiator.mts","../../src/internal/core/invalidator.mts","../../src/internal/lifecycle/lifecycle-event-bus.mts","../../src/internal/holder/holder-manager.mts","../../src/internal/core/token-processor.mts","../../src/internal/core/service-locator.mts","../../src/container/container.mts","../../src/decorators/factory.decorator.mts","../../src/event-emitter.mts"],"sourcesContent":["export enum InjectableScope {\n /**\n * Singleton scope: The instance is created once and shared across the application.\n */\n Singleton = 'Singleton',\n /**\n * Instance scope: A new instance is created for each injection.\n */\n Transient = 'Transient',\n /**\n * Request scope: The instance is created once per request and shared within that request context.\n */\n Request = 'Request',\n}\n","export enum InjectableType {\n Class = 'Class',\n Factory = 'Factory',\n}\n","import type { z, ZodObject, ZodOptional, ZodRecord } from 'zod/v4'\n\nimport type { FactoryContext } from '../internal/context/factory-context.mjs'\n\nexport type ClassType = new (...args: any[]) => any\nexport type ClassTypeWithoutArguments = new () => any\nexport type ClassTypeWithArgument<Arg> = new (arg: Arg) => any\nexport type ClassTypeWithOptionalArgument<Arg> = new (arg?: Arg) => any\n\nexport type ClassTypeWithInstance<T> = new (...args: any[]) => T\nexport type ClassTypeWithInstanceAndArgument<T, Arg> = new (arg: Arg) => T\nexport type ClassTypeWithInstanceAndOptionalArgument<T, Arg> = new (\n arg?: Arg,\n) => T\n\nexport type BaseInjectionTokenSchemaType = ZodObject | ZodRecord\n\nexport type OptionalInjectionTokenSchemaType =\n | ZodOptional<ZodObject>\n | ZodOptional<ZodRecord>\n\nexport type InjectionTokenSchemaType =\n | BaseInjectionTokenSchemaType\n | OptionalInjectionTokenSchemaType\n\nexport class InjectionToken<\n // oxlint-disable-next-line no-unused-vars\n T,\n S extends InjectionTokenSchemaType | unknown = unknown,\n // oxlint-disable-next-line no-unused-vars\n Required extends boolean = S extends ZodOptional<ZodObject>\n ? false\n : S extends ZodOptional<ZodRecord>\n ? false\n : S extends ZodObject\n ? true\n : S extends ZodRecord\n ? true\n : false,\n> {\n public id = globalThis.crypto.randomUUID()\n private formattedName: string | null = null\n\n constructor(\n public readonly name: string | symbol | ClassType,\n public readonly schema: ZodObject | undefined,\n ) {}\n\n static create<T extends ClassType>(\n name: T,\n ): InjectionToken<InstanceType<T>, undefined>\n static create<T extends ClassType, Schema extends InjectionTokenSchemaType>(\n name: T,\n schema: Schema,\n ): Schema['_def']['type'] extends 'ZodOptional'\n ? InjectionToken<InstanceType<T>, Schema, false>\n : InjectionToken<InstanceType<T>, Schema, true>\n static create<T>(name: string | symbol): InjectionToken<T, undefined>\n static create<T, Schema extends InjectionTokenSchemaType>(\n name: string | any,\n schema: Schema,\n ): InjectionToken<T, Schema>\n static create(name: string | symbol, schema?: unknown) {\n // @ts-expect-error\n return new InjectionToken(name, schema)\n }\n\n static bound<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n value: z.input<S>,\n ): BoundInjectionToken<T, S> {\n return new BoundInjectionToken(token, value)\n }\n\n static factory<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n factory: (ctx: FactoryContext) => Promise<z.input<S>>,\n ): FactoryInjectionToken<T, S> {\n return new FactoryInjectionToken(token, factory)\n }\n\n static refineType<T>(\n token: BoundInjectionToken<any, any>,\n ): BoundInjectionToken<T, any> {\n return token as BoundInjectionToken<T, any>\n }\n\n toString() {\n if (this.formattedName) {\n return this.formattedName\n }\n const { name } = this\n if (typeof name === 'function') {\n const className = name.name\n this.formattedName = `${className}(${this.id})`\n } else if (typeof name === 'symbol') {\n this.formattedName = `${name.toString()}(${this.id})`\n } else {\n this.formattedName = `${name}(${this.id})`\n }\n\n return this.formattedName\n }\n}\n\nexport class BoundInjectionToken<T, S extends InjectionTokenSchemaType> {\n public id: string\n public name: string | symbol | ClassType\n public schema: InjectionTokenSchemaType\n\n constructor(\n public readonly token: InjectionToken<T, S>,\n public readonly value: z.input<S>,\n ) {\n this.name = token.name\n this.id = token.id\n this.schema = token.schema as InjectionTokenSchemaType\n }\n\n toString() {\n return this.token.toString()\n }\n}\n\nexport class FactoryInjectionToken<T, S extends InjectionTokenSchemaType> {\n public value?: z.input<S>\n public resolved = false\n public id: string\n public name: string | symbol | ClassType\n public schema: InjectionTokenSchemaType\n\n constructor(\n public readonly token: InjectionToken<T, S>,\n public readonly factory: (ctx: FactoryContext) => Promise<z.input<S>>,\n ) {\n this.name = token.name\n this.id = token.id\n this.schema = token.schema as InjectionTokenSchemaType\n }\n\n async resolve(ctx: FactoryContext): Promise<z.input<S>> {\n if (!this.value) {\n this.value = await this.factory(ctx)\n this.resolved = true\n }\n return this.value\n }\n\n toString() {\n return this.token.toString()\n }\n}\n\nexport type AnyInjectableType =\n | ClassType\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>\n\nexport type InjectionTokenType =\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>\n","import type { ClassType, InjectionToken } from './injection-token.mjs'\n\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\n\nexport type FactoryRecord<Instance = any, Schema = any> = {\n scope: InjectableScope\n originalToken: InjectionToken<Instance, Schema>\n target: ClassType\n type: InjectableType\n}\n\nexport class Registry {\n private readonly factories = new Map<string, FactoryRecord>()\n\n constructor(private readonly parent?: Registry) {}\n\n has(token: InjectionToken<any, any>): boolean {\n if (this.factories.has(token.id)) {\n return true\n }\n if (this.parent) {\n return this.parent.has(token)\n }\n return false\n }\n\n get<Instance, Schema>(\n token: InjectionToken<Instance, Schema>,\n ): FactoryRecord<Instance, Schema> {\n const factory = this.factories.get(token.id)\n if (!factory) {\n if (this.parent) {\n return this.parent.get(token)\n }\n throw new Error(`[Registry] No factory found for ${token.toString()}`)\n }\n return factory\n }\n\n set<Instance, Schema>(\n token: InjectionToken<Instance, Schema>,\n scope: InjectableScope,\n target: ClassType,\n type: InjectableType,\n ) {\n this.factories.set(token.id, { scope, originalToken: token, target, type })\n }\n\n delete(token: InjectionToken<any, any>) {\n this.factories.delete(token.id)\n }\n\n /**\n * Updates the scope of an already registered factory.\n * This is useful when you need to dynamically change a service's scope\n * (e.g., when a singleton controller has request-scoped dependencies).\n *\n * @param token The injection token to update\n * @param scope The new scope to set\n * @returns true if the scope was updated, false if the token was not found\n */\n updateScope(token: InjectionToken<any, any>, scope: InjectableScope): boolean {\n const factory = this.factories.get(token.id)\n if (factory) {\n factory.scope = scope\n return true\n }\n if (this.parent) {\n return this.parent.updateScope(token, scope)\n }\n return false\n }\n}\n\nexport const globalRegistry = new Registry()\n","export const InjectableTokenMeta = Symbol.for('InjectableTokenMeta')\n","import { z } from 'zod/v4'\n\nimport type {\n BaseInjectionTokenSchemaType,\n ClassType,\n ClassTypeWithArgument,\n ClassTypeWithInstance,\n ClassTypeWithInstanceAndArgument,\n ClassTypeWithInstanceAndOptionalArgument,\n ClassTypeWithOptionalArgument,\n ClassTypeWithoutArguments,\n InjectionTokenSchemaType,\n OptionalInjectionTokenSchemaType,\n} from '../token/injection-token.mjs'\nimport type { Registry } from '../token/registry.mjs'\n\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\nimport { InjectionToken } from '../token/injection-token.mjs'\nimport { globalRegistry } from '../token/registry.mjs'\nimport { InjectableTokenMeta } from '../symbols/index.mjs'\n\nexport interface InjectableOptions {\n scope?: InjectableScope\n token?: InjectionToken<any, any>\n schema?: InjectionTokenSchemaType\n registry?: Registry\n}\n// #1 Simple constructorless class\nexport function Injectable(): <T extends ClassTypeWithoutArguments>(\n target: T,\n context?: ClassDecoratorContext,\n) => T\nexport function Injectable(options: {\n scope?: InjectableScope\n registry: Registry\n}): <T extends ClassTypeWithoutArguments>(\n target: T,\n context?: ClassDecoratorContext,\n) => T\nexport function Injectable(options: {\n scope: InjectableScope\n}): <T extends ClassTypeWithoutArguments>(\n target: T,\n context?: ClassDecoratorContext,\n) => T\n// #2 Class with schema\nexport function Injectable<Schema extends InjectionTokenSchemaType>(options: {\n scope?: InjectableScope\n schema: Schema\n registry?: Registry\n}): <T extends ClassTypeWithArgument<z.output<Schema>>>(\n target: T,\n context?: ClassDecoratorContext,\n) => T\n\n// #3 Class with typeless token and schema\nexport function Injectable<Type, Schema>(options: {\n scope?: InjectableScope\n token: InjectionToken<Type, Schema>\n registry?: Registry\n}): Schema extends BaseInjectionTokenSchemaType // #3.1 Check that schema is an object or a record\n ? Type extends undefined\n ? <T extends ClassTypeWithArgument<z.output<Schema>>>( // #3.1.1 Typeless token\n target: T,\n context?: ClassDecoratorContext,\n ) => T\n : <T extends ClassTypeWithInstanceAndArgument<Type, z.output<Schema>>>( // #3.1.2 Typed token\n target: T,\n context?: ClassDecoratorContext,\n ) => T\n : Schema extends OptionalInjectionTokenSchemaType // #3.2 Check that schema is an optional object or a record\n ? Type extends undefined\n ? <T extends ClassTypeWithOptionalArgument<z.output<Schema>>>( // #3.2.1 Typeless token\n target: T,\n context?: ClassDecoratorContext,\n ) => T\n : <\n // #3.2.2 Typed token\n T extends ClassTypeWithInstanceAndOptionalArgument<\n Type,\n z.output<Schema>\n >,\n >(\n target: T,\n context?: ClassDecoratorContext,\n ) => T\n : Schema extends undefined // #3.3 Check that schema is undefined\n ? <R extends ClassTypeWithInstance<Type>>( // #3.3.1 Token must have a type\n target: R,\n context?: ClassDecoratorContext,\n ) => R\n : never // #3.4 Cannot use a token without a type and schema\n\nexport function Injectable({\n scope = InjectableScope.Singleton,\n token,\n schema,\n registry = globalRegistry,\n}: InjectableOptions = {}) {\n return <T extends ClassType>(\n target: T,\n context?: ClassDecoratorContext,\n ): T => {\n if (\n (context && context.kind !== 'class') ||\n (target instanceof Function && !context)\n ) {\n throw new Error(\n '[ServiceLocator] @Injectable decorator can only be used on classes.',\n )\n }\n if (schema && token) {\n throw new Error(\n '[ServiceLocator] @Injectable decorator cannot have both a token and a schema',\n )\n }\n let injectableToken: InjectionToken<any, any> =\n token ?? InjectionToken.create(target, schema as InjectionTokenSchemaType)\n\n registry.set(injectableToken, scope, target, InjectableType.Class)\n\n // @ts-expect-error\n target[InjectableTokenMeta] = injectableToken\n\n return target\n }\n}\n","export enum DIErrorCode {\n FactoryNotFound = 'FactoryNotFound',\n FactoryTokenNotResolved = 'FactoryTokenNotResolved',\n InstanceNotFound = 'InstanceNotFound',\n InstanceDestroying = 'InstanceDestroying',\n CircularDependency = 'CircularDependency',\n UnknownError = 'UnknownError',\n}\n\nexport class DIError extends Error {\n public readonly context?: Record<string, unknown>\n\n constructor(\n public readonly code: DIErrorCode,\n public readonly message: string,\n context?: Record<string, unknown>,\n ) {\n super(message)\n this.context = context\n }\n\n // Static factory methods for common error types\n static factoryNotFound(name: string): DIError {\n return new DIError(\n DIErrorCode.FactoryNotFound,\n `Factory ${name} not found`,\n { name },\n )\n }\n\n static factoryTokenNotResolved(token: string | symbol | unknown): DIError {\n return new DIError(\n DIErrorCode.FactoryTokenNotResolved,\n `Factory token not resolved: ${token?.toString() ?? 'unknown'}`,\n { token },\n )\n }\n\n static instanceNotFound(name: string): DIError {\n return new DIError(\n DIErrorCode.InstanceNotFound,\n `Instance ${name} not found`,\n { name },\n )\n }\n\n static instanceDestroying(name: string): DIError {\n return new DIError(\n DIErrorCode.InstanceDestroying,\n `Instance ${name} destroying`,\n { name },\n )\n }\n\n static unknown(\n message: string | Error,\n context?: Record<string, unknown>,\n ): DIError {\n if (message instanceof Error) {\n return new DIError(DIErrorCode.UnknownError, message.message, {\n ...context,\n parent: message,\n })\n }\n return new DIError(DIErrorCode.UnknownError, message, context)\n }\n\n static circularDependency(cycle: string[]): DIError {\n const cycleStr = cycle.join(' -> ')\n return new DIError(\n DIErrorCode.CircularDependency,\n `Circular dependency detected: ${cycleStr}`,\n { cycle },\n )\n }\n}\n","import type { IAsyncLocalStorage } from './async-local-storage.types.mjs'\n\n/**\n * A synchronous-only polyfill for AsyncLocalStorage.\n *\n * This provides the same API as Node's AsyncLocalStorage but only works\n * for synchronous code paths. It uses a simple stack-based approach.\n *\n * Limitations:\n * - Context does NOT propagate across async boundaries (setTimeout, promises, etc.)\n * - Only suitable for environments where DI resolution is synchronous\n *\n * This is acceptable for browser environments where:\n * 1. Constructors are typically synchronous\n * 2. Circular dependency detection mainly needs sync tracking\n */\nexport class SyncLocalStorage<T> implements IAsyncLocalStorage<T> {\n private stack: T[] = []\n\n /**\n * Runs a function within the given store context.\n * The context is only available synchronously within the function.\n */\n run<R>(store: T, fn: () => R): R {\n this.stack.push(store)\n try {\n return fn()\n } finally {\n this.stack.pop()\n }\n }\n\n /**\n * Gets the current store value, or undefined if not in a context.\n */\n getStore(): T | undefined {\n return this.stack.length > 0 ? this.stack[this.stack.length - 1] : undefined\n }\n\n /**\n * Exits the current context and runs the function without any store.\n * This matches AsyncLocalStorage.exit() behavior.\n */\n exit<R>(fn: () => R): R {\n const savedStack = this.stack\n this.stack = []\n try {\n return fn()\n } finally {\n this.stack = savedStack\n }\n }\n}\n","/**\n * Browser implementation using SyncLocalStorage.\n *\n * This module is used in browser environments where async_hooks is not available.\n * It provides synchronous-only context tracking which is sufficient for\n * browser-based DI resolution.\n */\n\nimport { SyncLocalStorage } from './sync-local-storage.mjs'\n\nexport type { IAsyncLocalStorage } from './async-local-storage.types.mjs'\n\nexport function createAsyncLocalStorage<T>() {\n return new SyncLocalStorage<T>()\n}\n\nexport function isUsingNativeAsyncLocalStorage(): boolean {\n return false\n}\n","import type { InstanceHolder } from '../holder/instance-holder.mjs'\nimport type { IAsyncLocalStorage } from './async-local-storage.types.mjs'\n\nimport { createAsyncLocalStorage } from './async-local-storage.mjs'\n\n/**\n * Data stored in the resolution context during service instantiation.\n */\nexport interface ResolutionContextData {\n /** The holder that is currently being instantiated */\n waiterHolder: InstanceHolder\n /** Function to get a holder by name (for cycle detection) */\n getHolder: (name: string) => InstanceHolder | undefined\n}\n\n/**\n * AsyncLocalStorage for tracking the current resolution context.\n *\n * This allows tracking which service is being instantiated even across\n * async boundaries (like when inject() is called inside a constructor).\n * Essential for circular dependency detection.\n *\n * The actual implementation varies by environment:\n * - Production: No-op (returns undefined, run() just calls fn directly)\n * - Development: Real AsyncLocalStorage with full async tracking\n * - Browser: SyncLocalStorage for synchronous-only tracking\n */\nlet resolutionContext: IAsyncLocalStorage<ResolutionContextData> | null = null\n\nfunction getResolutionContext(): IAsyncLocalStorage<ResolutionContextData> {\n if (!resolutionContext) {\n resolutionContext = createAsyncLocalStorage<ResolutionContextData>()\n }\n return resolutionContext\n}\n\n/**\n * Runs a function within a resolution context.\n *\n * The context tracks which holder is currently being instantiated,\n * allowing circular dependency detection to work correctly.\n *\n * @param waiterHolder The holder being instantiated\n * @param getHolder Function to retrieve holders by name\n * @param fn The function to run within the context\n */\nexport function withResolutionContext<T>(\n waiterHolder: InstanceHolder,\n getHolder: (name: string) => InstanceHolder | undefined,\n fn: () => T,\n): T {\n return getResolutionContext().run({ waiterHolder, getHolder }, fn)\n}\n\n/**\n * Gets the current resolution context, if any.\n *\n * Returns undefined if we're not inside a resolution context\n * (e.g., when resolving a top-level service that has no parent).\n */\nexport function getCurrentResolutionContext():\n | ResolutionContextData\n | undefined {\n return getResolutionContext().getStore()\n}\n\n/**\n * Runs a function outside any resolution context.\n *\n * This is useful for async injections that should not participate\n * in circular dependency detection since they don't block.\n *\n * @param fn The function to run without resolution context\n */\nexport function withoutResolutionContext<T>(fn: () => T): T {\n // Run with undefined context to clear any current context\n return getResolutionContext().run(\n undefined as unknown as ResolutionContextData,\n fn,\n )\n}\n","import type { z, ZodObject, ZodType } from 'zod/v4'\n\nimport type { FactoryContext } from '../internal/context/factory-context.mjs'\nimport type {\n BoundInjectionToken,\n ClassType,\n ClassTypeWithArgument,\n ClassTypeWithoutArguments,\n FactoryInjectionToken,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '../token/injection-token.mjs'\nimport type {\n Factorable,\n FactorableWithArgs,\n} from '../interfaces/factory.interface.mjs'\nimport type {\n InjectRequest,\n InjectState,\n Join,\n UnionToArray,\n} from './types.mjs'\n\nimport { InjectableTokenMeta } from '../symbols/index.mjs'\nimport { withoutResolutionContext } from '../internal/context/resolution-context.mjs'\n\nexport interface Injectors {\n // #1 Simple class\n asyncInject<T extends ClassTypeWithoutArguments>(\n token: T,\n ): InstanceType<T> extends Factorable<infer R>\n ? Promise<R>\n : Promise<InstanceType<T>>\n asyncInject<Args, T extends ClassTypeWithArgument<Args>>(\n token: T,\n args: Args,\n ): Promise<InstanceType<T>>\n asyncInject<\n Schema extends InjectionTokenSchemaType,\n R,\n T extends FactorableWithArgs<R, Schema>,\n >(\n token: T,\n args: z.input<Schema>,\n ): Promise<R>\n\n // #2 Token with required Schema\n asyncInject<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n ): Promise<T>\n // #3 Token with optional Schema\n asyncInject<T, S extends InjectionTokenSchemaType, R extends boolean>(\n token: InjectionToken<T, S, R>,\n ): R extends false\n ? Promise<T>\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<\n UnionToArray<keyof Type>,\n ', '\n >}`\n : 'Error: Your token requires args'\n // #4 Token with no Schema\n asyncInject<T>(token: InjectionToken<T, undefined>): Promise<T>\n asyncInject<T>(token: BoundInjectionToken<T, any>): Promise<T>\n asyncInject<T>(token: FactoryInjectionToken<T, any>): Promise<T>\n\n inject<T extends ClassTypeWithoutArguments>(\n token: T,\n ): InstanceType<T> extends Factorable<infer R> ? R : InstanceType<T>\n inject<Args, T extends ClassTypeWithArgument<Args>>(\n token: T,\n args: Args,\n ): InstanceType<T>\n inject<\n Schema extends InjectionTokenSchemaType,\n R,\n T extends FactorableWithArgs<R, Schema>,\n >(\n token: T,\n args: z.input<Schema>,\n ): R\n\n inject<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n ): T\n // #3 Token with optional Schema\n inject<T, S extends InjectionTokenSchemaType, R extends boolean>(\n token: InjectionToken<T, S, R>,\n ): R extends false\n ? T\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<\n UnionToArray<keyof Type>,\n ', '\n >}`\n : 'Error: Your token requires args'\n inject<T>(token: InjectionToken<T, undefined>): T\n inject<T>(token: BoundInjectionToken<T, any>): T\n inject<T>(token: FactoryInjectionToken<T, any>): T\n\n /**\n * Optional injection that returns null if the service fails to initialize\n * or is not available. This is useful when you want to inject a service\n * that may not be configured or may fail gracefully.\n *\n * @example\n * ```ts\n * class MyService {\n * constructor() {\n * const optionalService = optional(OptionalServiceToken)\n * // optionalService will be null if initialization fails\n * if (optionalService) {\n * optionalService.doSomething()\n * }\n * }\n * }\n * ```\n */\n optional<T extends ClassType>(\n token: T,\n ): (InstanceType<T> extends Factorable<infer R> ? R : InstanceType<T>) | null\n optional<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n ): T | null\n optional<T, S extends InjectionTokenSchemaType, R extends boolean>(\n token: InjectionToken<T, S, R>,\n ): R extends false\n ? T | null\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<\n UnionToArray<keyof Type>,\n ', '\n >}`\n : 'Error: Your token requires args'\n optional<T>(token: InjectionToken<T, undefined>): T | null\n optional<T>(token: BoundInjectionToken<T, any>): T | null\n optional<T>(token: FactoryInjectionToken<T, any>): T | null\n\n wrapSyncInit(\n cb: () => any,\n ): (injectState?: InjectState) => [any, Promise<any>[], InjectState]\n\n provideFactoryContext(context: FactoryContext | null): FactoryContext | null\n}\n\nexport function getInjectors() {\n let currentFactoryContext: FactoryContext | null = null\n\n function provideFactoryContext(\n context: FactoryContext,\n ): FactoryContext | null {\n const original = currentFactoryContext\n currentFactoryContext = context\n return original\n }\n function getFactoryContext(): FactoryContext {\n if (!currentFactoryContext) {\n throw new Error(\n '[Injector] Trying to access injection context outside of a injectable context',\n )\n }\n return currentFactoryContext\n }\n\n let promiseCollector: null | ((promise: Promise<any>) => void) = null\n let injectState: InjectState | null = null\n\n function getRequest(\n token: InjectionToken<any>,\n args?: unknown,\n skipCycleTracking = false,\n ) {\n if (!injectState) {\n throw new Error(\n '[Injector] Trying to make a request outside of a injectable context',\n )\n }\n if (injectState.isFrozen) {\n const idx = injectState.currentIndex++\n const request = injectState.requests[idx]\n if (request.token !== token) {\n throw new Error(\n `[Injector] Wrong token order. Expected ${request.token.toString()} but got ${token.toString()}`,\n )\n }\n return request\n }\n let result: any = null\n let error: Error | null = null\n\n // For async inject, we run outside the resolution context to skip cycle tracking.\n // This is because asyncInject returns a promise that doesn't block the constructor,\n // so it cannot cause a deadlock even with circular dependencies.\n const doInject = () =>\n getFactoryContext()\n .inject(token as any, args as any)\n .then((r) => {\n result = r\n return r\n })\n .catch((e) => {\n // We don't throw here because we have a mechanism to handle errors\n error = e\n })\n\n const promise = skipCycleTracking\n ? withoutResolutionContext(doInject)\n : doInject()\n\n const request: InjectRequest = {\n token,\n promise,\n get result() {\n return result\n },\n get error() {\n return error\n },\n }\n injectState.requests.push(request)\n injectState.currentIndex++\n\n return request\n }\n\n function asyncInject(\n token:\n | ClassType\n | InjectionToken<any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args?: unknown,\n ) {\n if (!injectState) {\n throw new Error(\n '[Injector] Trying to access inject outside of a injectable context',\n )\n }\n // @ts-expect-error In case we have a class\n const realToken = token[InjectableTokenMeta] ?? token\n // Pass skipCycleTracking=true because asyncInject returns a promise that doesn't\n // block the constructor, so it cannot cause a deadlock even with circular dependencies.\n const request = getRequest(realToken, args, true)\n return request.promise.then((result) => {\n if (request.error) {\n // We throw here because we want to fail the asyncInject call if the dependency fails to initialize\n throw request.error\n }\n return result\n })\n }\n\n function wrapSyncInit(cb: () => any) {\n return (previousState?: InjectState) => {\n const promises: Promise<any>[] = []\n const originalPromiseCollector = promiseCollector\n const originalInjectState = injectState\n injectState = previousState\n ? {\n ...previousState,\n currentIndex: 0,\n }\n : {\n currentIndex: 0,\n isFrozen: false,\n requests: [],\n }\n promiseCollector = (promise) => {\n promises.push(promise)\n }\n const result = cb()\n promiseCollector = originalPromiseCollector\n const newInjectState = {\n ...injectState,\n isFrozen: true,\n }\n injectState = originalInjectState\n return [result, promises, newInjectState]\n }\n }\n\n function inject<\n T,\n Token extends\n | InjectionToken<T>\n | BoundInjectionToken<T, any>\n | FactoryInjectionToken<T, any>,\n S extends ZodObject | unknown = Token['schema'],\n >(token: Token, args?: S extends ZodObject ? z.input<S> : never): T {\n // @ts-expect-error In case we have a class\n const realToken = token[InjectableTokenMeta] ?? token\n\n if (!injectState) {\n throw new Error(\n '[Injector] Trying to access inject outside of a injectable context',\n )\n }\n\n const instance = getFactoryContext().container.tryGetSync(\n realToken,\n args,\n )\n if (!instance) {\n const request = getRequest(realToken, args)\n if (request.error) {\n throw request.error\n } else if (request.result) {\n return request.result\n }\n if (promiseCollector) {\n promiseCollector(request.promise)\n }\n // Return a dynamic proxy that looks up the instance when accessed\n return new Proxy(\n {},\n {\n get() {\n throw new Error(\n `[Injector] Trying to access ${realToken.toString()} before it's initialized, please move the code to a onServiceInit method`,\n )\n },\n },\n ) as unknown as T\n }\n return instance as unknown as T\n }\n\n function optional<\n T,\n Token extends\n | InjectionToken<T>\n | BoundInjectionToken<T, any>\n | FactoryInjectionToken<T, any>,\n S extends ZodObject | unknown = Token['schema'],\n >(token: Token, args?: S extends ZodObject ? z.input<S> : never): T | null {\n try {\n return inject(token, args)\n } catch {\n // If injection fails, return null instead of throwing\n return null\n }\n }\n\n const injectors: Injectors = {\n asyncInject,\n inject,\n optional,\n wrapSyncInit,\n provideFactoryContext,\n } as Injectors\n\n return injectors\n}\n","import type { ClassType, InjectionToken } from '../token/injection-token.mjs'\n\nimport { InjectableTokenMeta } from '../symbols/index.mjs'\n\nexport function getInjectableToken<R>(\n target: ClassType,\n): R extends { create(...args: any[]): infer V }\n ? InjectionToken<V>\n : InjectionToken<R> {\n // @ts-expect-error We inject the token into the class itself\n const token = target[InjectableTokenMeta] as InjectionToken<any, any>\n if (!token) {\n throw new Error(\n `[ServiceLocator] Class ${target.name} is not decorated with @Injectable.`,\n )\n }\n // @ts-expect-error We detect factory or class\n return token\n}\n","import type { Injectors } from './utils/index.mjs'\n\nimport { getInjectors } from './utils/index.mjs'\n\nexport const defaultInjectors = getInjectors()\n\nexport const asyncInject: Injectors['asyncInject'] =\n defaultInjectors.asyncInject\n\nexport const inject: Injectors['inject'] = defaultInjectors.inject\n\nexport const optional: Injectors['optional'] = defaultInjectors.optional\n\nexport const wrapSyncInit: Injectors['wrapSyncInit'] =\n defaultInjectors.wrapSyncInit\n\nexport const provideFactoryContext: Injectors['provideFactoryContext'] =\n defaultInjectors.provideFactoryContext\n","import type { InstanceHolder } from '../holder/instance-holder.mjs'\n\n/**\n * Whether we're running in production mode.\n * In production, circular dependency detection is skipped for performance.\n */\nconst isProduction = process.env.NODE_ENV === 'production'\n\n/**\n * Detects circular dependencies by analyzing the waitingFor relationships\n * between service holders.\n *\n * Uses BFS to traverse the waitingFor graph starting from a target holder\n * and checks if following the chain leads back to the waiter, indicating a circular dependency.\n *\n * Note: In production (NODE_ENV === 'production'), detection is skipped for performance.\n */\nexport class CircularDetector {\n /**\n * Detects if waiting for `targetName` from `waiterName` would create a cycle.\n *\n * This works by checking if `targetName` (or any holder in its waitingFor chain)\n * is currently waiting for `waiterName`. If so, waiting would create a deadlock.\n *\n * In production mode, this always returns null to skip the BFS traversal overhead.\n *\n * @param waiterName The name of the holder that wants to wait\n * @param targetName The name of the holder being waited on\n * @param getHolder Function to retrieve a holder by name\n * @returns The cycle path if a cycle is detected, null otherwise\n */\n static detectCycle(\n waiterName: string,\n targetName: string,\n getHolder: (name: string) => InstanceHolder | undefined,\n ): string[] | null {\n // Skip circular dependency detection in production for performance\n if (isProduction) {\n return null\n }\n\n // Use BFS to find if there's a path from targetName back to waiterName\n const visited = new Set<string>()\n const queue: Array<{ name: string; path: string[] }> = [\n { name: targetName, path: [waiterName, targetName] },\n ]\n\n while (queue.length > 0) {\n const { name: currentName, path } = queue.shift()!\n\n // If we've reached back to the waiter, we have a cycle\n if (currentName === waiterName) {\n return path\n }\n\n // Skip if already visited\n if (visited.has(currentName)) {\n continue\n }\n visited.add(currentName)\n\n // Get the holder and check what it's waiting for\n const holder = getHolder(currentName)\n if (!holder) {\n continue\n }\n\n // Add all services this holder is waiting for to the queue\n for (const waitingForName of holder.waitingFor) {\n if (!visited.has(waitingForName)) {\n queue.push({\n name: waitingForName,\n path: [...path, waitingForName],\n })\n }\n }\n }\n\n // No path found from target back to waiter, no cycle\n return null\n }\n\n /**\n * Formats a cycle path into a human-readable string.\n *\n * @param cycle The cycle path (array of service names)\n * @returns Formatted string like \"ServiceA -> ServiceB -> ServiceA\"\n */\n static formatCycle(cycle: string[]): string {\n return cycle.join(' -> ')\n }\n}\n","import type { InjectableScope, InjectableType } from '../../enums/index.mjs'\n\n/**\n * Represents the lifecycle status of an instance holder.\n */\nexport enum InstanceStatus {\n /** Instance has been successfully created and is ready for use */\n Created = 'created',\n /** Instance is currently being created (async initialization in progress) */\n Creating = 'creating',\n /** Instance is being destroyed (cleanup in progress) */\n Destroying = 'destroying',\n /** Instance creation failed with an error */\n Error = 'error',\n}\n\n/** Callback function for instance effects */\nexport type InstanceEffect = () => void\n\n/** Callback function for instance destruction listeners */\nexport type InstanceDestroyListener = () => void | Promise<void>\n\n/**\n * Instance holder in the Creating state.\n * The instance is null while creation is in progress.\n */\nexport interface InstanceHolderCreating<Instance> {\n status: InstanceStatus.Creating\n name: string\n instance: null\n creationPromise: Promise<[undefined, Instance]> | null\n destroyPromise: null\n type: InjectableType\n scope: InjectableScope\n deps: Set<string>\n destroyListeners: InstanceDestroyListener[]\n createdAt: number\n /** Tracks which services this holder is currently waiting for (for circular dependency detection) */\n waitingFor: Set<string>\n}\n\n/**\n * Instance holder in the Created state.\n * The instance is available and ready for use.\n */\nexport interface InstanceHolderCreated<Instance> {\n status: InstanceStatus.Created\n name: string\n instance: Instance\n creationPromise: null\n destroyPromise: null\n type: InjectableType\n scope: InjectableScope\n deps: Set<string>\n destroyListeners: InstanceDestroyListener[]\n createdAt: number\n /** Tracks which services this holder is currently waiting for (for circular dependency detection) */\n waitingFor: Set<string>\n}\n\n/**\n * Instance holder in the Destroying state.\n * The instance may still be available but is being cleaned up.\n */\nexport interface InstanceHolderDestroying<Instance> {\n status: InstanceStatus.Destroying\n name: string\n instance: Instance | null\n creationPromise: null\n destroyPromise: Promise<void>\n type: InjectableType\n scope: InjectableScope\n deps: Set<string>\n destroyListeners: InstanceDestroyListener[]\n createdAt: number\n /** Tracks which services this holder is currently waiting for (for circular dependency detection) */\n waitingFor: Set<string>\n}\n\n/**\n * Instance holder in the Error state.\n * The instance field contains the error that occurred during creation.\n */\nexport interface InstanceHolderError {\n status: InstanceStatus.Error\n name: string\n instance: Error\n creationPromise: null\n destroyPromise: null\n type: InjectableType\n scope: InjectableScope\n deps: Set<string>\n destroyListeners: InstanceDestroyListener[]\n createdAt: number\n /** Tracks which services this holder is currently waiting for (for circular dependency detection) */\n waitingFor: Set<string>\n}\n\n/**\n * Holds the state of a service instance throughout its lifecycle.\n *\n * Tracks creation/destruction promises, dependency relationships,\n * destroy listeners, and current status (Creating, Created, Destroying, Error).\n */\nexport type InstanceHolder<Instance = unknown> =\n | InstanceHolderCreating<Instance>\n | InstanceHolderCreated<Instance>\n | InstanceHolderDestroying<Instance>\n | InstanceHolderError\n","import type { InstanceHolder } from './instance-holder.mjs'\n\nimport { InjectableScope, InjectableType } from '../../enums/index.mjs'\nimport { DIError } from '../../errors/index.mjs'\nimport { CircularDetector } from '../lifecycle/circular-detector.mjs'\nimport { InstanceStatus } from './instance-holder.mjs'\n\n/**\n * Result type for waitForHolderReady.\n * Returns either [undefined, holder] on success or [error] on failure.\n */\nexport type HolderReadyResult<T> = [undefined, InstanceHolder<T>] | [DIError]\n\n/**\n * Abstract base class providing common functionality for managing InstanceHolder objects.\n *\n * Provides shared patterns for holder storage, creation, and lifecycle management\n * used by both singleton (HolderManager) and request-scoped (RequestContext) managers.\n */\nexport abstract class BaseHolderManager {\n protected readonly _holders: Map<string, InstanceHolder>\n\n constructor(protected readonly logger: Console | null = null) {\n this._holders = new Map()\n }\n\n /**\n * Protected getter for accessing the holders map from subclasses.\n */\n protected get holders(): Map<string, InstanceHolder> {\n return this._holders\n }\n\n /**\n * Abstract method to get a holder by name. Each implementation defines its own return type\n * based on their specific error handling and validation needs.\n */\n abstract get(name: string): any\n\n /**\n * Abstract method to set a holder by name. Each implementation may have different validation logic.\n */\n abstract set(name: string, holder: InstanceHolder): void\n\n /**\n * Abstract method to check if a holder exists. Each implementation may have different validation logic.\n */\n abstract has(name: string): any\n\n /**\n * Deletes a holder by name.\n * @param name The name of the holder to delete\n * @returns true if the holder was deleted, false if it didn't exist\n */\n delete(name: string): boolean {\n return this._holders.delete(name)\n }\n\n /**\n * Filters holders based on a predicate function.\n * @param predicate Function to test each holder\n * @returns A new Map containing only the holders that match the predicate\n */\n filter(\n predicate: (value: InstanceHolder<any>, key: string) => boolean,\n ): Map<string, InstanceHolder> {\n return new Map(\n [...this._holders].filter(([key, value]) => predicate(value, key)),\n )\n }\n\n /**\n * Clears all holders from this manager.\n */\n clear(): void {\n this._holders.clear()\n }\n\n /**\n * Gets the number of holders currently managed.\n */\n size(): number {\n return this._holders.size\n }\n\n /**\n * Creates a new holder with Creating status and a deferred creation promise.\n * This is useful for creating placeholder holders that can be fulfilled later.\n * @param name The name of the instance\n * @param type The injectable type\n * @param scope The injectable scope\n * @param deps Optional set of dependencies\n * @returns A tuple containing the deferred promise and the holder\n */\n createCreatingHolder<Instance>(\n name: string,\n type: InjectableType,\n scope: InjectableScope,\n deps: Set<string> = new Set(),\n ): [\n ReturnType<typeof Promise.withResolvers<[undefined, Instance]>>,\n InstanceHolder<Instance>,\n ] {\n const deferred = Promise.withResolvers<[undefined, Instance]>()\n\n const holder: InstanceHolder<Instance> = {\n status: InstanceStatus.Creating,\n name,\n instance: null,\n creationPromise: deferred.promise,\n destroyPromise: null,\n type,\n scope,\n deps,\n destroyListeners: [],\n createdAt: Date.now(),\n waitingFor: new Set(),\n }\n\n return [deferred, holder]\n }\n\n /**\n * Creates a new holder with Created status and an actual instance.\n * This is useful for creating holders that already have their instance ready.\n * @param name The name of the instance\n * @param instance The actual instance to store\n * @param type The injectable type\n * @param scope The injectable scope\n * @param deps Optional set of dependencies\n * @returns The created holder\n */\n protected createCreatedHolder<Instance>(\n name: string,\n instance: Instance,\n type: InjectableType,\n scope: InjectableScope,\n deps: Set<string> = new Set(),\n ): InstanceHolder<Instance> {\n const holder: InstanceHolder<Instance> = {\n status: InstanceStatus.Created,\n name,\n instance,\n creationPromise: null,\n destroyPromise: null,\n type,\n scope,\n deps,\n destroyListeners: [],\n createdAt: Date.now(),\n waitingFor: new Set(),\n }\n\n return holder\n }\n\n /**\n * Gets all holder names currently managed.\n */\n getAllNames(): string[] {\n return Array.from(this._holders.keys())\n }\n\n /**\n * Gets all holders currently managed.\n */\n getAllHolders(): InstanceHolder[] {\n return Array.from(this._holders.values())\n }\n\n /**\n * Checks if this manager has any holders.\n */\n isEmpty(): boolean {\n return this._holders.size === 0\n }\n\n /**\n * Waits for a holder to be ready and returns the appropriate result.\n * This is a shared utility used by both singleton and request-scoped resolution.\n *\n * @param holder The holder to wait for\n * @param waiterHolder Optional holder that is doing the waiting (for circular dependency detection)\n * @param getHolder Optional function to retrieve holders by name (required if waiterHolder is provided)\n * @returns A promise that resolves with [undefined, holder] on success or [DIError] on failure\n */\n static async waitForHolderReady<T>(\n holder: InstanceHolder<T>,\n waiterHolder?: InstanceHolder,\n getHolder?: (name: string) => InstanceHolder | undefined,\n ): Promise<HolderReadyResult<T>> {\n switch (holder.status) {\n case InstanceStatus.Creating: {\n // Check for circular dependency before waiting\n if (waiterHolder && getHolder) {\n const cycle = CircularDetector.detectCycle(\n waiterHolder.name,\n holder.name,\n getHolder,\n )\n if (cycle) {\n return [DIError.circularDependency(cycle)]\n }\n\n // Track the waiting relationship\n waiterHolder.waitingFor.add(holder.name)\n }\n\n try {\n await holder.creationPromise\n } finally {\n // Clean up the waiting relationship\n if (waiterHolder) {\n waiterHolder.waitingFor.delete(holder.name)\n }\n }\n\n return BaseHolderManager.waitForHolderReady(\n holder,\n waiterHolder,\n getHolder,\n )\n }\n\n case InstanceStatus.Destroying:\n return [DIError.instanceDestroying(holder.name)]\n\n case InstanceStatus.Error:\n return [holder.instance as unknown as DIError]\n\n case InstanceStatus.Created:\n return [undefined, holder]\n\n default:\n return [DIError.instanceNotFound('unknown')]\n }\n }\n}\n","import type { InstanceHolder } from '../holder/instance-holder.mjs'\n\nimport { BaseHolderManager } from '../holder/base-holder-manager.mjs'\nimport { InjectableScope, InjectableType } from '../../enums/index.mjs'\nimport { InjectionToken } from '../../token/injection-token.mjs'\n\n/**\n * Interface for request context that manages pre-prepared instances for a specific request.\n *\n * Provides isolated storage for request-scoped services, enabling efficient\n * instantiation and cleanup within the lifecycle of a single request.\n */\nexport interface RequestContext {\n /**\n * Unique identifier for this request context.\n */\n readonly requestId: string\n\n /**\n * Instance holders for request-scoped services.\n */\n readonly holders: Map<string, InstanceHolder>\n\n /**\n * Priority for resolution in FactoryContext.inject method.\n * Higher values take precedence.\n */\n readonly priority: number\n\n /**\n * Request-specific metadata that can be used during instantiation.\n */\n readonly metadata: Map<string, any>\n\n /**\n * Timestamp when this context was created.\n */\n readonly createdAt: number\n\n /**\n * Adds a pre-prepared instance to this context.\n */\n addInstance(\n instanceName: string,\n instance: any,\n holder: InstanceHolder,\n ): void\n\n /**\n * Adds a pre-prepared instance to this context.\n */\n addInstance(token: InjectionToken<any, undefined>, instance: any): void\n\n /**\n * Gets an instance holder from this context.\n */\n get(instanceName: string): InstanceHolder | undefined\n\n /**\n * Sets an instance holder by name.\n */\n set(instanceName: string, holder: InstanceHolder): void\n\n /**\n * Checks if this context has a pre-prepared instance.\n */\n has(instanceName: string): boolean\n\n /**\n * Clears all instances and holders from this context.\n */\n clear(): void\n\n /**\n * Gets metadata value by key.\n */\n getMetadata(key: string): any | undefined\n\n /**\n * Sets metadata value by key.\n */\n setMetadata(key: string, value: any): void\n\n // Methods inherited from BaseHolderManager\n /**\n * Filters holders based on a predicate function.\n */\n filter(\n predicate: (\n value: InstanceHolder<any>,\n key: string,\n ) => boolean,\n ): Map<string, InstanceHolder>\n\n /**\n * Deletes a holder by name.\n */\n delete(name: string): boolean\n\n /**\n * Gets the number of holders currently managed.\n */\n size(): number\n\n /**\n * Checks if this manager has any holders.\n */\n isEmpty(): boolean\n}\n\n/** @deprecated Use RequestContext instead */\nexport type RequestContextHolder = RequestContext\n\n/**\n * Default implementation of RequestContext.\n *\n * Extends BaseHolderManager to provide holder management functionality\n * with request-specific metadata and lifecycle support.\n */\nexport class DefaultRequestContext\n extends BaseHolderManager\n implements RequestContext\n{\n public readonly metadata = new Map<string, any>()\n public readonly createdAt = Date.now()\n\n constructor(\n public readonly requestId: string,\n public readonly priority: number = 100,\n initialMetadata?: Record<string, any>,\n ) {\n super(null) // RequestContext doesn't need logging\n if (initialMetadata) {\n Object.entries(initialMetadata).forEach(([key, value]) => {\n this.metadata.set(key, value)\n })\n }\n }\n\n /**\n * Public getter for holders to maintain interface compatibility.\n */\n get holders(): Map<string, InstanceHolder> {\n return this._holders\n }\n\n /**\n * Gets a holder by name. For RequestContext, this is a simple lookup.\n */\n get(name: string): InstanceHolder | undefined {\n return this._holders.get(name)\n }\n\n /**\n * Sets a holder by name.\n */\n set(name: string, holder: InstanceHolder): void {\n this._holders.set(name, holder)\n }\n\n /**\n * Checks if a holder exists by name.\n */\n has(name: string): boolean {\n return this._holders.has(name)\n }\n\n addInstance(\n instanceName: string | InjectionToken<any, undefined>,\n instance: any,\n holder?: InstanceHolder,\n ): void {\n if (instanceName instanceof InjectionToken) {\n const name = instanceName.toString()\n const createdHolder = this.createCreatedHolder(\n name,\n instance,\n InjectableType.Class,\n InjectableScope.Singleton,\n new Set(),\n )\n this._holders.set(name, createdHolder)\n } else {\n if (!holder) {\n throw new Error('Holder is required when adding an instance by name')\n }\n this._holders.set(instanceName, holder)\n }\n }\n\n clear(): void {\n super.clear() // Use the base class clear method for holders\n this.metadata.clear()\n }\n\n getMetadata(key: string): any | undefined {\n return this.metadata.get(key)\n }\n\n setMetadata(key: string, value: any): void {\n this.metadata.set(key, value)\n }\n}\n\n/**\n * Creates a new request context with the given parameters.\n */\nexport function createRequestContext(\n requestId: string,\n priority: number = 100,\n initialMetadata?: Record<string, any>,\n): RequestContext {\n return new DefaultRequestContext(requestId, priority, initialMetadata)\n}\n","import type { RequestContext } from '../context/request-context.mjs'\nimport type { BaseHolderManager } from './base-holder-manager.mjs'\nimport type {\n HolderGetResult,\n IHolderStorage,\n} from './holder-storage.interface.mjs'\nimport type { InstanceHolder } from './instance-holder.mjs'\n\nimport { InjectableScope, InjectableType } from '../../enums/index.mjs'\nimport { DIError } from '../../errors/index.mjs'\nimport { InstanceStatus } from './instance-holder.mjs'\n\n/**\n * Storage implementation for Request-scoped services.\n *\n * Wraps a RequestContext instance from a ScopedContainer and provides\n * the IHolderStorage interface. This allows the InstanceResolver to work\n * with request-scoped storage using the same interface as singleton storage.\n */\nexport class RequestStorage implements IHolderStorage {\n readonly scope = InjectableScope.Request\n\n constructor(\n private readonly contextHolder: RequestContext,\n private readonly holderManager: BaseHolderManager,\n ) {}\n\n get<T = unknown>(instanceName: string): HolderGetResult<T> {\n const holder = this.contextHolder.get(instanceName)\n\n if (!holder) {\n return null\n }\n\n // Check holder status for error states\n switch (holder.status) {\n case InstanceStatus.Destroying:\n return [\n DIError.instanceDestroying(instanceName),\n holder as InstanceHolder<T>,\n ]\n\n case InstanceStatus.Error:\n return [\n holder.instance as unknown as DIError,\n holder as InstanceHolder<T>,\n ]\n\n case InstanceStatus.Creating:\n case InstanceStatus.Created:\n return [undefined, holder as InstanceHolder<T>]\n\n default:\n return null\n }\n }\n\n set(instanceName: string, holder: InstanceHolder): void {\n this.contextHolder.set(instanceName, holder)\n }\n\n delete(instanceName: string): boolean {\n return this.contextHolder.delete(instanceName)\n }\n\n createHolder<T>(\n instanceName: string,\n type: InjectableType,\n deps: Set<string>,\n ): [\n ReturnType<typeof Promise.withResolvers<[undefined, T]>>,\n InstanceHolder<T>,\n ] {\n // Use the holderManager's createCreatingHolder method\n // which is inherited from BaseHolderManager\n return this.holderManager.createCreatingHolder<T>(\n instanceName,\n type,\n this.scope,\n deps,\n )\n }\n\n handles(scope: InjectableScope): boolean {\n return scope === InjectableScope.Request\n }\n\n // ============================================================================\n // ITERATION AND QUERY\n // ============================================================================\n\n getAllNames(): string[] {\n const names: string[] = []\n for (const [name] of this.contextHolder.holders) {\n names.push(name)\n }\n return names\n }\n\n forEach(callback: (name: string, holder: InstanceHolder) => void): void {\n for (const [name, holder] of this.contextHolder.holders) {\n callback(name, holder)\n }\n }\n\n findByInstance(instance: unknown): InstanceHolder | null {\n for (const holder of this.contextHolder.holders.values()) {\n if (holder.instance === instance) {\n return holder\n }\n }\n return null\n }\n\n findDependents(instanceName: string): string[] {\n const dependents: string[] = []\n\n // Check request-scoped holders\n for (const [name, holder] of this.contextHolder.holders) {\n if (holder.deps.has(instanceName)) {\n dependents.push(name)\n }\n }\n\n // Also check singleton holders - a singleton may depend on this request-scoped service\n for (const [name, holder] of this.holderManager.filter(() => true)) {\n if (holder.deps.has(instanceName)) {\n dependents.push(name)\n }\n }\n\n return dependents\n }\n}\n","import type { z, ZodType } from 'zod/v4'\n\nimport type { Container } from './container.mjs'\nimport type {\n BoundInjectionToken,\n ClassType,\n ClassTypeWithArgument,\n FactoryInjectionToken,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '../token/injection-token.mjs'\nimport type { IContainer } from '../interfaces/container.interface.mjs'\nimport type { IHolderStorage } from '../internal/holder/holder-storage.interface.mjs'\nimport type { Factorable } from '../interfaces/factory.interface.mjs'\nimport type { Registry } from '../token/registry.mjs'\nimport type { RequestContext } from '../internal/context/request-context.mjs'\nimport type { InstanceHolder } from '../internal/holder/instance-holder.mjs'\nimport type { Join, UnionToArray } from '../utils/types.mjs'\n\nimport { BaseHolderManager } from '../internal/holder/base-holder-manager.mjs'\nimport { InjectableScope } from '../enums/index.mjs'\nimport { DIError } from '../errors/index.mjs'\nimport { DefaultRequestContext } from '../internal/context/request-context.mjs'\nimport { RequestStorage } from '../internal/holder/request-storage.mjs'\nimport { InstanceStatus } from '../internal/holder/instance-holder.mjs'\n\n/**\n * Request-scoped dependency injection container.\n *\n * Wraps a parent Container and provides isolated request-scoped instances\n * while delegating singleton and transient resolution to the parent.\n * This design eliminates race conditions that can occur with async operations\n * when multiple requests are processed concurrently.\n */\nexport class ScopedContainer implements IContainer {\n private readonly requestContextHolder: RequestContext\n private readonly holderStorage: IHolderStorage\n private disposed = false\n\n constructor(\n private readonly parent: Container,\n private readonly registry: Registry,\n public readonly requestId: string,\n metadata?: Record<string, any>,\n priority: number = 100,\n ) {\n this.requestContextHolder = new DefaultRequestContext(\n requestId,\n priority,\n metadata,\n )\n // Create storage once and reuse for all resolutions\n this.holderStorage = new RequestStorage(\n this.requestContextHolder,\n this.parent.getServiceLocator().getManager(),\n )\n }\n\n /**\n * Gets the request context holder for this scoped container.\n */\n getRequestContextHolder(): RequestContext {\n return this.requestContextHolder\n }\n\n /**\n * Gets the holder storage for this scoped container.\n * Used by InstanceResolver for request-scoped resolution.\n */\n getHolderStorage(): IHolderStorage {\n return this.holderStorage\n }\n\n /**\n * Gets the request ID for this scoped container.\n */\n getRequestId(): string {\n return this.requestId\n }\n\n /**\n * Gets the parent container.\n */\n getParent(): Container {\n return this.parent\n }\n\n /**\n * Gets metadata from the request context.\n */\n getMetadata(key: string): any | undefined {\n return this.requestContextHolder.getMetadata(key)\n }\n\n /**\n * Sets metadata on the request context.\n */\n setMetadata(key: string, value: any): void {\n this.requestContextHolder.setMetadata(key, value)\n }\n\n /**\n * Adds a pre-prepared instance to the request context.\n */\n addInstance(token: InjectionToken<any, undefined>, instance: any): void {\n this.requestContextHolder.addInstance(token, instance)\n }\n\n /**\n * Gets an instance from the container.\n * Request-scoped services are resolved from this container's context.\n * All other services are delegated to the parent container.\n */\n // #1 Simple class\n get<T extends ClassType>(\n token: T,\n ): InstanceType<T> extends Factorable<infer R>\n ? Promise<R>\n : Promise<InstanceType<T>>\n // #1.1 Simple class with args\n get<T extends ClassTypeWithArgument<R>, R>(\n token: T,\n args: R,\n ): Promise<InstanceType<T>>\n // #2 Token with required Schema\n get<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n ): Promise<T>\n // #3 Token with optional Schema\n get<T, S extends InjectionTokenSchemaType, R extends boolean>(\n token: InjectionToken<T, S, R>,\n ): R extends false\n ? Promise<T>\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<\n UnionToArray<keyof Type>,\n ', '\n >}`\n : 'Error: Your token requires args'\n // #4 Token with no Schema\n get<T>(token: InjectionToken<T, undefined>): Promise<T>\n get<T>(token: BoundInjectionToken<T, any>): Promise<T>\n get<T>(token: FactoryInjectionToken<T, any>): Promise<T>\n\n async get(\n token:\n | ClassType\n | InjectionToken<any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args?: unknown,\n ): Promise<any> {\n if (this.disposed) {\n throw DIError.unknown(\n `ScopedContainer for request ${this.requestId} has been disposed`,\n )\n }\n\n // Get the actual injection token using TokenProcessor for consistency\n const tokenProcessor = this.parent.getServiceLocator().getTokenProcessor()\n const actualToken = tokenProcessor.normalizeToken(token)\n\n // Check if this is a request-scoped service\n if (this.isRequestScoped(actualToken)) {\n return this.resolveRequestScoped(actualToken, args)\n }\n\n // Delegate to parent for singleton/transient services\n // Pass this ScopedContainer so nested inject() calls work correctly\n return this.parent.getWithContext(token, args, this)\n }\n\n /**\n * Invalidates a service and its dependencies.\n * For request-scoped services, invalidation is handled within this context.\n */\n async invalidate(service: unknown): Promise<void> {\n // Check if the service is in our request context\n const holder = this.holderStorage.findByInstance(service)\n if (holder) {\n // Use the shared Invalidator with our request-scoped storage\n await this.parent\n .getServiceLocator()\n .getInvalidator()\n .invalidateWithStorage(holder.name, this.holderStorage, 1, {\n emitEvents: false, // Request-scoped services don't emit global events\n })\n return\n }\n\n // Delegate to parent for singleton services\n await this.parent.invalidate(service)\n }\n\n /**\n * Checks if a service is registered.\n */\n isRegistered(token: any): boolean {\n return this.parent.isRegistered(token)\n }\n\n /**\n * Disposes this scoped container and cleans up all request-scoped instances.\n * This is an alias for endRequest() for IContainer compatibility.\n */\n async dispose(): Promise<void> {\n await this.endRequest()\n }\n\n /**\n * Ends the request and cleans up all request-scoped instances.\n * Uses the invalidation system to properly cascade to dependent singletons.\n */\n async endRequest(): Promise<void> {\n if (this.disposed) {\n return\n }\n\n this.disposed = true\n\n // Use clearAllWithStorage to properly invalidate all request-scoped services\n // This will cascade invalidation to singletons that depend on request-scoped services\n await this.parent\n .getServiceLocator()\n .getInvalidator()\n .clearAllWithStorage(this.holderStorage, {\n waitForSettlement: true,\n maxRounds: 10,\n })\n\n // Clear the context (any remaining holders that weren't invalidated)\n this.requestContextHolder.clear()\n\n // Remove from parent's active requests\n this.parent.removeActiveRequest(this.requestId)\n }\n\n /**\n * Waits for all pending operations to complete.\n */\n async ready(): Promise<void> {\n await this.parent.ready()\n }\n\n /**\n * @internal\n * Attempts to get an instance synchronously if it already exists and is ready.\n * For request-scoped services, checks this container's context first.\n * For other services, delegates to the parent container.\n *\n * Returns null if the instance doesn't exist or is not yet ready (still creating).\n */\n tryGetSync<T>(token: any, args?: any): T | null {\n const tokenProcessor = this.parent.getServiceLocator().getTokenProcessor()\n const actualToken = tokenProcessor.normalizeToken(token)\n\n // Check if this is a request-scoped service\n if (this.isRequestScoped(actualToken)) {\n const serviceLocator = this.parent.getServiceLocator()\n const instanceName = serviceLocator.getInstanceIdentifier(token, args)\n const holder = this.requestContextHolder.get(instanceName)\n // Only return if holder exists AND is in Created status\n if (\n holder &&\n holder.status === InstanceStatus.Created\n ) {\n return holder.instance as T\n }\n return null\n }\n\n // Delegate to parent for non-request-scoped\n return this.parent.tryGetSync(token, args)\n }\n\n /**\n * Checks if a token is for a request-scoped service.\n */\n private isRequestScoped(token: any): boolean {\n // Handle BoundInjectionToken and FactoryInjectionToken using TokenProcessor\n const tokenProcessor = this.parent.getServiceLocator().getTokenProcessor()\n const realToken = tokenProcessor.getRealToken(token)\n\n if (!this.registry.has(realToken)) {\n return false\n }\n\n const record = this.registry.get(realToken)\n return record.scope === InjectableScope.Request\n }\n\n /**\n * Resolves a request-scoped service from this container's context.\n * Uses locking to prevent duplicate initialization during concurrent resolution.\n */\n private async resolveRequestScoped(token: any, args: unknown): Promise<any> {\n // Get the instance name\n const serviceLocator = this.parent.getServiceLocator()\n const instanceName = serviceLocator.getInstanceIdentifier(token, args)\n\n // Check if we already have this instance (or one is being created)\n const existingHolder = this.requestContextHolder.get(instanceName)\n if (existingHolder) {\n // If the holder is in error state, remove it so we can retry\n if (existingHolder.status === InstanceStatus.Error) {\n this.requestContextHolder.delete(instanceName)\n // Fall through to create a new instance\n } else {\n // Wait for the holder to be ready if it's still being created\n // This prevents race conditions where multiple concurrent calls\n // might try to create the same service\n const [error, readyHolder] =\n await BaseHolderManager.waitForHolderReady(existingHolder)\n if (error) {\n throw error\n }\n return readyHolder.instance\n }\n }\n\n // Create new instance using parent's resolution mechanism\n // but store it in our request context\n return this.parent.resolveForRequest(token, args, this)\n }\n\n /**\n * Stores an instance in the request context.\n * Called by Container during request-scoped service resolution.\n */\n storeRequestInstance(\n instanceName: string,\n instance: any,\n holder: InstanceHolder,\n ): void {\n this.requestContextHolder.addInstance(instanceName, instance, holder)\n }\n\n /**\n * Gets an existing instance from the request context.\n * Called by Container during resolution to check for existing instances.\n */\n getRequestInstance(\n instanceName: string,\n ): InstanceHolder | undefined {\n return this.requestContextHolder.get(instanceName)\n }\n\n /**\n * Generates a prefixed event name for request-scoped services.\n * Format: {requestId}:{instanceName}\n */\n getPrefixedEventName(instanceName: string): string {\n return `${this.requestId}:${instanceName}`\n }\n}\n","import type { HolderManager } from './holder-manager.mjs'\nimport type {\n HolderGetResult,\n IHolderStorage,\n} from './holder-storage.interface.mjs'\nimport type { InstanceHolder } from './instance-holder.mjs'\n\nimport { InjectableScope, InjectableType } from '../../enums/index.mjs'\nimport { DIErrorCode } from '../../errors/index.mjs'\n\n/**\n * Storage implementation for Singleton-scoped services.\n *\n * Wraps a HolderManager instance and provides the IHolderStorage interface.\n * This allows the InstanceResolver to work with singleton storage\n * using the same interface as request-scoped storage.\n */\nexport class SingletonStorage implements IHolderStorage {\n readonly scope = InjectableScope.Singleton\n\n constructor(private readonly manager: HolderManager) {}\n\n get<T = unknown>(instanceName: string): HolderGetResult<T> {\n const [error, holder] = this.manager.get(instanceName)\n\n if (!error) {\n return [undefined, holder as InstanceHolder<T>]\n }\n\n // Handle different error types\n switch (error.code) {\n case DIErrorCode.InstanceNotFound:\n return null\n\n case DIErrorCode.InstanceDestroying:\n return [error, holder as InstanceHolder<T> | undefined]\n\n default:\n return [error]\n }\n }\n\n set(instanceName: string, holder: InstanceHolder): void {\n this.manager.set(instanceName, holder)\n }\n\n delete(instanceName: string): boolean {\n return this.manager.delete(instanceName)\n }\n\n createHolder<T>(\n instanceName: string,\n type: InjectableType,\n deps: Set<string>,\n ): [\n ReturnType<typeof Promise.withResolvers<[undefined, T]>>,\n InstanceHolder<T>,\n ] {\n return this.manager.createCreatingHolder<T>(\n instanceName,\n type,\n this.scope,\n deps,\n )\n }\n\n handles(scope: InjectableScope): boolean {\n return scope === InjectableScope.Singleton\n }\n\n // ============================================================================\n // ITERATION AND QUERY\n // ============================================================================\n\n getAllNames(): string[] {\n return this.manager.getAllNames()\n }\n\n forEach(\n callback: (name: string, holder: InstanceHolder) => void,\n ): void {\n for (const [name, holder] of this.manager.filter(() => true)) {\n callback(name, holder)\n }\n }\n\n findByInstance(instance: unknown): InstanceHolder | null {\n for (const [, holder] of this.manager.filter(\n (h) => h.instance === instance,\n )) {\n return holder\n }\n return null\n }\n\n findDependents(instanceName: string): string[] {\n const dependents: string[] = []\n for (const [name, holder] of this.manager.filter(() => true)) {\n if (holder.deps.has(instanceName)) {\n dependents.push(name)\n }\n }\n return dependents\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-empty-object-type */\nimport type { z, ZodObject, ZodOptional } from 'zod/v4'\n\nimport type { ScopedContainer } from '../../container/scoped-container.mjs'\nimport type { IContainer } from '../../interfaces/container.interface.mjs'\nimport type {\n AnyInjectableType,\n InjectionTokenSchemaType,\n InjectionTokenType,\n} from '../../token/injection-token.mjs'\nimport type { Registry } from '../../token/registry.mjs'\nimport type { FactoryContext } from '../context/factory-context.mjs'\nimport type { HolderManager } from '../holder/holder-manager.mjs'\nimport type { IHolderStorage } from '../holder/holder-storage.interface.mjs'\nimport type { InstanceHolder } from '../holder/instance-holder.mjs'\nimport type { Instantiator } from './instantiator.mjs'\nimport type { ServiceLocator } from './service-locator.mjs'\nimport type { TokenProcessor } from './token-processor.mjs'\n\nimport { InjectableScope } from '../../enums/index.mjs'\nimport { DIError, DIErrorCode } from '../../errors/index.mjs'\nimport {\n BoundInjectionToken,\n FactoryInjectionToken,\n InjectionToken,\n} from '../../token/injection-token.mjs'\nimport {\n getCurrentResolutionContext,\n withResolutionContext,\n} from '../context/resolution-context.mjs'\nimport { BaseHolderManager } from '../holder/base-holder-manager.mjs'\nimport { InstanceStatus } from '../holder/instance-holder.mjs'\nimport { SingletonStorage } from '../holder/singleton-storage.mjs'\n\n/**\n * Resolves instances from tokens, handling caching, creation, and scope rules.\n *\n * Uses the Storage Strategy pattern for unified singleton/request-scoped handling.\n * Coordinates with Instantiator for actual service creation.\n */\nexport class InstanceResolver {\n private readonly singletonStorage: IHolderStorage\n\n constructor(\n private readonly registry: Registry,\n private readonly manager: HolderManager,\n private readonly instantiator: Instantiator,\n private readonly tokenProcessor: TokenProcessor,\n private readonly logger: Console | null = null,\n private readonly serviceLocator: ServiceLocator,\n ) {\n this.singletonStorage = new SingletonStorage(manager)\n }\n\n // ============================================================================\n // PUBLIC RESOLUTION METHODS\n // ============================================================================\n\n /**\n * Resolves an instance for the given token and arguments.\n * This method is used for singleton and transient services.\n *\n * @param token The injection token\n * @param args Optional arguments\n * @param contextContainer The container to use for creating FactoryContext\n */\n async resolveInstance(\n token: AnyInjectableType,\n args: any,\n contextContainer: IContainer,\n ): Promise<[undefined, any] | [DIError]> {\n return this.resolveWithStorage(\n token,\n args,\n contextContainer,\n this.singletonStorage,\n )\n }\n\n /**\n * Resolves a request-scoped instance for a ScopedContainer.\n * The service will be stored in the ScopedContainer's request context.\n *\n * @param token The injection token\n * @param args Optional arguments\n * @param scopedContainer The ScopedContainer that owns the request context\n */\n async resolveRequestScopedInstance(\n token: AnyInjectableType,\n args: any,\n scopedContainer: ScopedContainer,\n ): Promise<[undefined, any] | [DIError]> {\n // Use the cached storage from ScopedContainer\n return this.resolveWithStorage(\n token,\n args,\n scopedContainer,\n scopedContainer.getHolderStorage(),\n scopedContainer,\n )\n }\n\n // ============================================================================\n // UNIFIED RESOLUTION (Storage Strategy Pattern)\n // ============================================================================\n\n /**\n * Unified resolution method that works with any IHolderStorage.\n * This eliminates duplication between singleton and request-scoped resolution.\n *\n * IMPORTANT: The check-and-store logic is carefully designed to avoid race conditions.\n * The storage check and holder creation must happen synchronously (no awaits between).\n *\n * @param token The injection token\n * @param args Optional arguments\n * @param contextContainer The container for FactoryContext\n * @param storage The storage strategy to use\n * @param scopedContainer Optional scoped container for request-scoped services\n */\n private async resolveWithStorage(\n token: AnyInjectableType,\n args: any,\n contextContainer: IContainer,\n storage: IHolderStorage,\n scopedContainer?: ScopedContainer,\n ): Promise<[undefined, any] | [DIError]> {\n // Step 1: Resolve token and prepare instance name\n const [err, data] = await this.resolveTokenAndPrepareInstanceName(\n token,\n args,\n contextContainer,\n )\n if (err) {\n return [err]\n }\n\n const { instanceName, validatedArgs, realToken } = data!\n\n // Step 2: Check for existing holder SYNCHRONOUSLY (no await between check and store)\n // This is critical for preventing race conditions with concurrent resolution\n const getResult = storage.get(instanceName)\n\n if (getResult !== null) {\n const [error, holder] = getResult\n if (!error && holder) {\n // Found existing holder - wait for it to be ready\n const readyResult = await this.waitForInstanceReady(holder)\n if (readyResult[0]) {\n return [readyResult[0]]\n }\n return [undefined, readyResult[1]!.instance]\n }\n // Handle error states (destroying, etc.)\n if (error) {\n const handledResult = await this.handleStorageError(\n instanceName,\n error,\n holder,\n storage,\n )\n if (handledResult) {\n return handledResult\n }\n }\n }\n\n // Step 3: Create new instance and store it\n // NOTE: Holder is stored synchronously inside createAndStoreInstance before any await\n const [createError, holder] = await this.createAndStoreInstance(\n instanceName,\n realToken,\n validatedArgs,\n contextContainer,\n storage,\n scopedContainer,\n )\n if (createError) {\n return [createError]\n }\n\n return [undefined, holder!.instance]\n }\n\n /**\n * Handles storage error states (destroying, error, etc.).\n * Returns a result if handled, null if should proceed with creation.\n */\n private async handleStorageError(\n instanceName: string,\n error: DIError,\n holder: InstanceHolder | undefined,\n storage: IHolderStorage,\n ): Promise<[undefined, any] | [DIError] | null> {\n switch (error.code) {\n case DIErrorCode.InstanceDestroying:\n // Wait for destruction then retry\n this.logger?.log(\n `[InstanceResolver] Instance ${instanceName} is being destroyed, waiting...`,\n )\n if (holder?.destroyPromise) {\n await holder.destroyPromise\n }\n // Re-check after destruction\n const newResult = storage.get(instanceName)\n if (newResult !== null && !newResult[0]) {\n const readyResult = await this.waitForInstanceReady(newResult[1]!)\n if (readyResult[0]) {\n return [readyResult[0]]\n }\n return [undefined, readyResult[1]!.instance]\n }\n return null // Proceed with creation\n\n default:\n // For error states, remove the failed holder from storage so we can retry\n if (holder) {\n this.logger?.log(\n `[InstanceResolver] Removing failed instance ${instanceName} from storage to allow retry`,\n )\n storage.delete(instanceName)\n }\n return null // Proceed with creation\n }\n }\n\n /**\n * Creates a new instance and stores it using the provided storage strategy.\n * This unified method replaces instantiateServiceFromRegistry and createRequestScopedInstance.\n *\n * For transient services, the instance is created but not stored (no caching).\n */\n private async createAndStoreInstance<Instance>(\n instanceName: string,\n realToken: InjectionToken<Instance, any>,\n args: any,\n contextContainer: IContainer,\n storage: IHolderStorage,\n scopedContainer?: ScopedContainer,\n ): Promise<[undefined, InstanceHolder<Instance>] | [DIError]> {\n this.logger?.log(\n `[InstanceResolver]#createAndStoreInstance() Creating instance for ${instanceName}`,\n )\n\n if (!this.registry.has(realToken)) {\n return [DIError.factoryNotFound(realToken.name.toString())]\n }\n\n const ctx = this.createFactoryContext(contextContainer)\n const record = this.registry.get<Instance, any>(realToken)\n const { scope, type } = record\n\n // For transient services, don't use storage locking - create directly\n if (scope === InjectableScope.Transient) {\n return this.createTransientInstance(instanceName, record, args, ctx)\n }\n\n // Create holder in \"Creating\" state using registry scope, not storage scope\n const [deferred, holder] = this.manager.createCreatingHolder<Instance>(\n instanceName,\n type,\n scope,\n ctx.deps,\n )\n\n // Store holder immediately (for lock mechanism)\n storage.set(instanceName, holder)\n\n // Create a getHolder function that looks up holders from both the manager and storage\n const getHolder = (name: string): InstanceHolder | undefined => {\n // First check the storage (which might be request-scoped)\n const storageResult = storage.get(name)\n if (storageResult !== null) {\n const [, storageHolder] = storageResult\n if (storageHolder) return storageHolder\n }\n // Fall back to the singleton manager\n const [, managerHolder] = this.manager.get(name)\n return managerHolder\n }\n\n // Start async instantiation within the resolution context\n // This allows circular dependency detection to track the waiter\n withResolutionContext(holder, getHolder, () => {\n this.instantiator\n .instantiateService(ctx, record, args)\n .then(async (result: [undefined, Instance] | [DIError]) => {\n const [error, instance] =\n result.length === 2 ? result : [result[0], undefined]\n await this.handleInstantiationResult(\n instanceName,\n holder,\n ctx,\n deferred,\n scope,\n error,\n instance,\n scopedContainer,\n )\n })\n .catch(async (error: Error) => {\n await this.handleInstantiationError(\n instanceName,\n holder,\n deferred,\n scope,\n error,\n )\n })\n .catch(() => {\n // Suppress unhandled rejections from the async chain.\n // Errors are communicated to awaiters via deferred.reject() which\n // rejects holder.creationPromise. This catch is a safety net for\n // any errors that might occur in the error handling itself.\n })\n })\n\n // Wait for instance to be ready\n return this.waitForInstanceReady(holder)\n }\n\n /**\n * Creates a transient instance without storage or locking.\n * Each call creates a new instance.\n */\n private async createTransientInstance<Instance>(\n instanceName: string,\n record: any,\n args: any,\n ctx: FactoryContext & {\n deps: Set<string>\n getDestroyListeners: () => (() => void)[]\n },\n ): Promise<[undefined, InstanceHolder<Instance>] | [DIError]> {\n this.logger?.log(\n `[InstanceResolver]#createTransientInstance() Creating transient instance for ${instanceName}`,\n )\n\n // Create a temporary holder for resolution context (transient instances can still have deps)\n const tempHolder: InstanceHolder<Instance> = {\n status: InstanceStatus.Creating,\n name: instanceName,\n instance: null,\n creationPromise: null,\n destroyPromise: null,\n type: record.type,\n scope: InjectableScope.Transient,\n deps: ctx.deps,\n destroyListeners: [],\n createdAt: Date.now(),\n waitingFor: new Set(),\n }\n\n // Create a getHolder function for resolution context\n const getHolder = (name: string): InstanceHolder | undefined => {\n const [, managerHolder] = this.manager.get(name)\n return managerHolder\n }\n\n // Run instantiation within resolution context for cycle detection\n const [error, instance] = await withResolutionContext(\n tempHolder,\n getHolder,\n () => this.instantiator.instantiateService(ctx, record, args),\n )\n\n if (error) {\n return [error as DIError]\n }\n\n // Create a holder for the transient instance (not stored, just for return consistency)\n const holder: InstanceHolder<Instance> = {\n status: InstanceStatus.Created,\n name: instanceName,\n instance: instance as Instance,\n creationPromise: null,\n destroyPromise: null,\n type: record.type,\n scope: InjectableScope.Transient,\n deps: ctx.deps,\n destroyListeners: ctx.getDestroyListeners(),\n createdAt: Date.now(),\n waitingFor: new Set(),\n }\n\n return [undefined, holder]\n }\n\n /**\n * Gets a synchronous instance (for sync operations).\n */\n getSyncInstance<\n Instance,\n Schema extends InjectionTokenSchemaType | undefined,\n >(\n token: AnyInjectableType,\n args: Schema extends ZodObject\n ? z.input<Schema>\n : Schema extends ZodOptional<ZodObject>\n ? z.input<Schema> | undefined\n : undefined,\n contextContainer: IContainer,\n ): Instance | null {\n const [err, { actualToken, validatedArgs }] =\n this.tokenProcessor.validateAndResolveTokenArgs(token, args)\n if (err) {\n return null\n }\n const instanceName = this.tokenProcessor.generateInstanceName(\n actualToken,\n validatedArgs,\n )\n\n // Check if this is a ScopedContainer and the service is request-scoped\n if ('getRequestInstance' in contextContainer) {\n const scopedContainer = contextContainer as ScopedContainer\n const requestHolder = scopedContainer.getRequestInstance(instanceName)\n if (requestHolder) {\n return requestHolder.instance as Instance\n }\n }\n\n // Try singleton manager\n const [error, holder] = this.manager.get(instanceName)\n if (error) {\n return null\n }\n return holder.instance as Instance\n }\n\n /**\n * Internal method to resolve token args and create instance name.\n * Handles factory token resolution and validation.\n */\n private async resolveTokenAndPrepareInstanceName(\n token: AnyInjectableType,\n args: any,\n contextContainer: IContainer,\n ): Promise<\n | [\n undefined,\n {\n instanceName: string\n validatedArgs: any\n actualToken: InjectionTokenType\n realToken: InjectionToken<any, any>\n },\n ]\n | [DIError]\n > {\n const [err, { actualToken, validatedArgs }] =\n this.tokenProcessor.validateAndResolveTokenArgs(token, args)\n if (err instanceof DIError && err.code === DIErrorCode.UnknownError) {\n return [err]\n } else if (\n err instanceof DIError &&\n err.code === DIErrorCode.FactoryTokenNotResolved &&\n actualToken instanceof FactoryInjectionToken\n ) {\n this.logger?.log(\n `[InstanceResolver]#resolveTokenAndPrepareInstanceName() Factory token not resolved, resolving it`,\n )\n await actualToken.resolve(this.createFactoryContext(contextContainer))\n return this.resolveTokenAndPrepareInstanceName(\n token,\n undefined,\n contextContainer,\n )\n }\n const instanceName = this.tokenProcessor.generateInstanceName(\n actualToken,\n validatedArgs,\n )\n // Determine the real token (the actual InjectionToken that will be used for resolution)\n const realToken =\n actualToken instanceof BoundInjectionToken ||\n actualToken instanceof FactoryInjectionToken\n ? actualToken.token\n : actualToken\n return [undefined, { instanceName, validatedArgs, actualToken, realToken }]\n }\n\n // ============================================================================\n // INSTANTIATION HANDLERS\n // ============================================================================\n\n /**\n * Waits for an instance holder to be ready and returns the appropriate result.\n * Uses the shared utility from BaseHolderManager.\n * Passes the current resolution context for circular dependency detection.\n */\n private waitForInstanceReady<T>(\n holder: InstanceHolder<T>,\n ): Promise<[undefined, InstanceHolder<T>] | [DIError]> {\n // Get the current resolution context (if we're inside an instantiation)\n const ctx = getCurrentResolutionContext()\n\n return BaseHolderManager.waitForHolderReady(\n holder,\n ctx?.waiterHolder,\n ctx?.getHolder,\n )\n }\n\n /**\n * Handles the result of service instantiation.\n */\n private async handleInstantiationResult(\n instanceName: string,\n holder: InstanceHolder<any>,\n ctx: FactoryContext & {\n deps: Set<string>\n getDestroyListeners: () => (() => void)[]\n },\n deferred: any,\n scope: InjectableScope,\n error: any,\n instance: any,\n scopedContainer?: ScopedContainer,\n ): Promise<void> {\n holder.destroyListeners = ctx.getDestroyListeners()\n holder.creationPromise = null\n\n if (error) {\n await this.handleInstantiationError(\n instanceName,\n holder,\n deferred,\n scope,\n error,\n )\n } else {\n await this.handleInstantiationSuccess(\n instanceName,\n holder,\n ctx,\n deferred,\n instance,\n scopedContainer,\n )\n }\n }\n\n /**\n * Handles successful service instantiation.\n */\n private async handleInstantiationSuccess(\n instanceName: string,\n holder: InstanceHolder<any>,\n ctx: FactoryContext & {\n deps: Set<string>\n getDestroyListeners: () => (() => void)[]\n },\n deferred: any,\n instance: any,\n scopedContainer?: ScopedContainer,\n ): Promise<void> {\n holder.instance = instance\n holder.status = InstanceStatus.Created\n\n // Set up dependency invalidation listeners\n if (ctx.deps.size > 0) {\n ctx.deps.forEach((dependency: string) => {\n holder.destroyListeners.push(\n this.serviceLocator.getEventBus().on(dependency, 'destroy', () => {\n this.logger?.log(\n `[InstanceResolver] Dependency ${dependency} destroyed, invalidating ${instanceName}`,\n )\n this.serviceLocator.getInvalidator().invalidate(instanceName)\n }),\n )\n\n // For request-scoped services, also listen with prefixed event name\n if (scopedContainer) {\n const prefixedDependency =\n scopedContainer.getPrefixedEventName(dependency)\n holder.destroyListeners.push(\n this.serviceLocator\n .getEventBus()\n .on(prefixedDependency, 'destroy', () => {\n this.logger?.log(\n `[InstanceResolver] Request-scoped dependency ${dependency} destroyed, invalidating ${instanceName}`,\n )\n // For request-scoped, we need to invalidate within the scoped container\n scopedContainer.invalidate(instance)\n }),\n )\n }\n })\n }\n\n // Note: Event emission would need access to the event bus\n this.logger?.log(\n `[InstanceResolver] Instance ${instanceName} created successfully`,\n )\n deferred.resolve([undefined, instance])\n }\n\n /**\n * Handles service instantiation errors.\n */\n private async handleInstantiationError(\n instanceName: string,\n holder: InstanceHolder<any>,\n deferred: any,\n scope: InjectableScope,\n error: any,\n ): Promise<void> {\n this.logger?.error(\n `[InstanceResolver] Error creating instance for ${instanceName}`,\n error,\n )\n\n holder.status = InstanceStatus.Error\n holder.instance = error\n holder.creationPromise = null\n\n if (scope === InjectableScope.Singleton) {\n this.logger?.log(\n `[InstanceResolver] Singleton ${instanceName} failed, will be invalidated`,\n )\n // Fire-and-forget invalidation - don't await as it could cause deadlocks\n // Suppress any potential rejections since the primary error is already handled\n this.serviceLocator\n .getInvalidator()\n .invalidate(instanceName)\n .catch(() => {\n // Suppress - primary error is communicated via deferred.reject()\n })\n }\n\n deferred.reject(error)\n }\n\n // ============================================================================\n // FACTORY CONTEXT\n // ============================================================================\n\n /**\n * Creates a factory context for dependency injection during service instantiation.\n */\n private createFactoryContext(contextContainer: IContainer): FactoryContext & {\n getDestroyListeners: () => (() => void)[]\n deps: Set<string>\n } {\n return this.tokenProcessor.createFactoryContext(contextContainer)\n }\n}\n","import type { FactoryRecord } from '../../token/registry.mjs'\nimport type { Injectors } from '../../utils/get-injectors.mjs'\nimport type { FactoryContext } from '../context/factory-context.mjs'\n\nimport { InjectableType } from '../../enums/index.mjs'\nimport { DIError } from '../../errors/index.mjs'\n\n/**\n * Creates service instances from registry records.\n *\n * Handles both class-based (@Injectable) and factory-based (@Factory) services,\n * managing the instantiation lifecycle including sync initialization retries\n * and lifecycle hook invocation (onServiceInit, onServiceDestroy).\n */\nexport class Instantiator {\n constructor(private readonly injectors: Injectors) {}\n\n /**\n * Instantiates a service based on its registry record.\n * @param ctx The factory context for dependency injection\n * @param record The factory record from the registry\n * @param args Optional arguments for the service\n * @returns Promise resolving to [undefined, instance] or [error]\n */\n async instantiateService<T>(\n ctx: FactoryContext,\n record: FactoryRecord<T, any>,\n args: any = undefined,\n ): Promise<[undefined, T] | [DIError]> {\n try {\n switch (record.type) {\n case InjectableType.Class:\n return this.instantiateClass(ctx, record, args)\n case InjectableType.Factory:\n return this.instantiateFactory(ctx, record, args)\n default:\n throw DIError.unknown(\n `[Instantiator] Unknown service type: ${record.type}`,\n )\n }\n } catch (error) {\n return [error instanceof DIError ? error : DIError.unknown(String(error))]\n }\n }\n\n /**\n * Instantiates a class-based service (Injectable decorator).\n * @param ctx The factory context for dependency injection\n * @param record The factory record from the registry\n * @param args Optional arguments for the service constructor\n * @returns Promise resolving to [undefined, instance] or [error]\n */\n private async instantiateClass<T>(\n ctx: FactoryContext,\n record: FactoryRecord<T, any>,\n args: any,\n ): Promise<[undefined, T] | [DIError]> {\n try {\n const tryLoad = this.injectors.wrapSyncInit(() => {\n const original = this.injectors.provideFactoryContext(ctx)\n let result = new record.target(...(args ? [args] : []))\n this.injectors.provideFactoryContext(original)\n return result\n })\n\n let [instance, promises, injectState] = tryLoad()\n if (promises.length > 0) {\n const results = await Promise.allSettled(promises)\n if (results.some((result) => result.status === 'rejected')) {\n throw DIError.unknown(\n `[Instantiator] Service ${record.target.name} cannot be instantiated.`,\n )\n }\n const newRes = tryLoad(injectState)\n instance = newRes[0]\n promises = newRes[1]\n }\n\n if (promises.length > 0) {\n console.error(`[Instantiator] ${record.target.name} has problem with it's definition.\n\n One or more of the dependencies are registered as a InjectableScope.Instance and are used with inject.\n\n Please use inject asyncInject of inject to load those dependencies.`)\n throw DIError.unknown(\n `[Instantiator] Service ${record.target.name} cannot be instantiated.`,\n )\n }\n\n // Handle lifecycle hooks\n if ('onServiceInit' in instance) {\n await (instance as any).onServiceInit()\n }\n if ('onServiceDestroy' in instance) {\n ctx.addDestroyListener(async () => {\n await (instance as any).onServiceDestroy()\n })\n }\n\n return [undefined, instance]\n } catch (error) {\n return [error instanceof DIError ? error : DIError.unknown(String(error))]\n }\n }\n\n /**\n * Instantiates a factory-based service (Factory decorator).\n * @param ctx The factory context for dependency injection\n * @param record The factory record from the registry\n * @param args Optional arguments for the factory\n * @returns Promise resolving to [undefined, instance] or [error]\n */\n private async instantiateFactory<T>(\n ctx: FactoryContext,\n record: FactoryRecord<T, any>,\n args: any,\n ): Promise<[undefined, T] | [DIError]> {\n try {\n const tryLoad = this.injectors.wrapSyncInit(() => {\n const original = this.injectors.provideFactoryContext(ctx)\n let result = new record.target()\n this.injectors.provideFactoryContext(original)\n return result\n })\n\n let [builder, promises, injectState] = tryLoad()\n if (promises.length > 0) {\n const results = await Promise.allSettled(promises)\n if (results.some((result) => result.status === 'rejected')) {\n throw DIError.unknown(\n `[Instantiator] Service ${record.target.name} cannot be instantiated.`,\n )\n }\n const newRes = tryLoad(injectState)\n builder = newRes[0]\n promises = newRes[1]\n }\n\n if (promises.length > 0) {\n console.error(`[Instantiator] ${record.target.name} has problem with it's definition.\n\n One or more of the dependencies are registered as a InjectableScope.Instance and are used with inject.\n\n Please use asyncInject instead of inject to load those dependencies.`)\n throw DIError.unknown(\n `[Instantiator] Service ${record.target.name} cannot be instantiated.`,\n )\n }\n\n if (typeof builder.create !== 'function') {\n throw DIError.unknown(\n `[Instantiator] Factory ${record.target.name} does not implement the create method.`,\n )\n }\n\n const instance = await builder.create(ctx, args)\n return [undefined, instance]\n } catch (error) {\n return [error instanceof DIError ? error : DIError.unknown(String(error))]\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { IHolderStorage } from '../holder/holder-storage.interface.mjs'\nimport type { LifecycleEventBus } from '../lifecycle/lifecycle-event-bus.mjs'\nimport type { InstanceHolder } from '../holder/instance-holder.mjs'\nimport type { HolderManager } from '../holder/holder-manager.mjs'\n\nimport { InstanceStatus } from '../holder/instance-holder.mjs'\nimport { SingletonStorage } from '../holder/singleton-storage.mjs'\n\nexport interface ClearAllOptions {\n /** Maximum number of invalidation rounds to prevent infinite loops (default: 10) */\n maxRounds?: number\n /** Whether to wait for all services to settle before starting (default: true) */\n waitForSettlement?: boolean\n}\n\nexport interface InvalidationOptions {\n /** Whether to emit events after invalidation (default: true for singletons) */\n emitEvents?: boolean\n /** Custom event emitter function */\n onInvalidated?: (instanceName: string) => Promise<void>\n /** Whether to cascade invalidation to dependents (default: true) */\n cascade?: boolean\n /** Internal: tracks services being invalidated in the current call chain to prevent circular loops */\n _invalidating?: Set<string>\n}\n\n/**\n * Manages graceful service cleanup with dependency-aware invalidation.\n *\n * Ensures services are destroyed in the correct order based on their dependencies.\n * Works with any IHolderStorage implementation, enabling unified invalidation\n * for both singleton and request-scoped services.\n */\nexport class Invalidator {\n private readonly storage: IHolderStorage\n\n constructor(\n manager: HolderManager,\n private readonly eventBus: LifecycleEventBus | null,\n private readonly logger: Console | null = null,\n ) {\n this.storage = new SingletonStorage(manager)\n }\n\n /**\n * Invalidates a service and all its dependencies.\n * Works with the configured storage (singleton by default).\n */\n invalidate(service: string, round = 1): Promise<any> {\n return this.invalidateWithStorage(service, this.storage, round)\n }\n\n /**\n * Invalidates a service using a specific storage.\n * This allows request-scoped invalidation using a RequestStorage.\n *\n * @param service The instance name to invalidate\n * @param storage The storage to use for this invalidation\n * @param round Current invalidation round (for recursion limiting)\n * @param options Additional options for invalidation behavior\n */\n async invalidateWithStorage(\n service: string,\n storage: IHolderStorage,\n round = 1,\n options: InvalidationOptions = {},\n ): Promise<void> {\n const { cascade = true, _invalidating = new Set<string>() } = options\n\n // Prevent infinite recursion from circular dependencies\n if (_invalidating.has(service)) {\n this.logger?.log(\n `[Invalidator] Skipping ${service} - already being invalidated in this chain`,\n )\n return\n }\n\n this.logger?.log(\n `[Invalidator] Starting invalidation process for ${service}`,\n )\n\n const result = storage.get(service)\n if (result === null) {\n return\n }\n\n // Mark this service as being invalidated\n _invalidating.add(service)\n\n // Pass the tracking set to cascaded invalidations\n const optionsWithTracking = { ...options, _invalidating }\n\n // Cascade invalidation: first invalidate all services that depend on this one\n if (cascade) {\n const dependents = storage.findDependents(service)\n for (const dependentName of dependents) {\n await this.invalidateWithStorage(dependentName, storage, round, optionsWithTracking)\n }\n }\n\n const [, holder] = result\n if (holder) {\n await this.invalidateHolderWithStorage(service, holder, storage, round, optionsWithTracking)\n }\n }\n\n /**\n * Gracefully clears all services using invalidation logic.\n * This method respects service dependencies and ensures proper cleanup order.\n * Services that depend on others will be invalidated first, then their dependencies.\n */\n async clearAll(options: ClearAllOptions = {}): Promise<void> {\n return this.clearAllWithStorage(this.storage, options)\n }\n\n /**\n * Gracefully clears all services in a specific storage.\n * This allows clearing request-scoped services using a RequestStorage.\n */\n async clearAllWithStorage(\n storage: IHolderStorage,\n options: ClearAllOptions = {},\n ): Promise<void> {\n const { maxRounds = 10, waitForSettlement = true } = options\n\n this.logger?.log(\n '[Invalidator] Starting graceful clearing of all services',\n )\n\n // Wait for all services to settle if requested\n if (waitForSettlement) {\n this.logger?.log(\n '[Invalidator] Waiting for all services to settle...',\n )\n await this.readyWithStorage(storage)\n }\n\n // Get all service names that need to be cleared\n const allServiceNames = storage.getAllNames()\n\n if (allServiceNames.length === 0) {\n this.logger?.log('[Invalidator] No services to clear')\n } else {\n this.logger?.log(\n `[Invalidator] Found ${allServiceNames.length} services to clear: ${allServiceNames.join(', ')}`,\n )\n\n // Clear services using dependency-aware invalidation\n await this.clearServicesWithDependencyAwarenessForStorage(\n allServiceNames,\n maxRounds,\n storage,\n )\n }\n\n this.logger?.log('[Invalidator] Graceful clearing completed')\n }\n\n /**\n * Waits for all services to settle (either created, destroyed, or error state).\n */\n async ready(): Promise<void> {\n return this.readyWithStorage(this.storage)\n }\n\n /**\n * Waits for all services in a specific storage to settle.\n */\n async readyWithStorage(storage: IHolderStorage): Promise<void> {\n const holders: InstanceHolder<any>[] = []\n storage.forEach((_: string, holder: InstanceHolder) => holders.push(holder))\n await Promise.all(\n holders.map((holder) => this.waitForHolderToSettle(holder)),\n )\n }\n\n // ============================================================================\n // INTERNAL INVALIDATION HELPERS\n // ============================================================================\n\n /**\n * Invalidates a single holder using a specific storage.\n */\n private async invalidateHolderWithStorage(\n key: string,\n holder: InstanceHolder<any>,\n storage: IHolderStorage,\n round: number,\n options: InvalidationOptions = {},\n ): Promise<void> {\n const { emitEvents = true, onInvalidated } = options\n\n await this.invalidateHolderByStatus(holder, round, {\n context: key,\n onCreationError: () =>\n this.logger?.error(\n `[Invalidator] ${key} creation triggered too many invalidation rounds`,\n ),\n onRecursiveInvalidate: () =>\n this.invalidateWithStorage(key, storage, round + 1, options),\n onDestroy: () =>\n this.destroyHolderWithStorage(key, holder, storage, emitEvents, onInvalidated),\n })\n }\n\n /**\n * Common invalidation logic for holders based on their status.\n */\n private async invalidateHolderByStatus(\n holder: InstanceHolder<any>,\n round: number,\n options: {\n context: string\n onCreationError: () => void\n onRecursiveInvalidate: () => Promise<void>\n onDestroy: () => Promise<void>\n },\n ): Promise<void> {\n switch (holder.status) {\n case InstanceStatus.Destroying:\n await holder.destroyPromise\n break\n\n case InstanceStatus.Creating:\n await holder.creationPromise\n if (round > 3) {\n options.onCreationError()\n return\n }\n await options.onRecursiveInvalidate()\n break\n\n default:\n await options.onDestroy()\n break\n }\n }\n\n /**\n * Destroys a holder using a specific storage.\n */\n private async destroyHolderWithStorage(\n key: string,\n holder: InstanceHolder<any>,\n storage: IHolderStorage,\n emitEvents: boolean,\n onInvalidated?: (instanceName: string) => Promise<void>,\n ): Promise<void> {\n holder.status = InstanceStatus.Destroying\n this.logger?.log(`[Invalidator] Invalidating ${key} and notifying listeners`)\n\n holder.destroyPromise = Promise.all(\n holder.destroyListeners.map((listener) => listener()),\n ).then(async () => {\n holder.destroyListeners = []\n holder.deps.clear()\n storage.delete(key)\n\n // Emit events if enabled and event bus exists\n if (emitEvents && this.eventBus) {\n await this.emitInstanceEvent(key, 'destroy')\n }\n\n // Call custom callback if provided\n if (onInvalidated) {\n await onInvalidated(key)\n }\n })\n\n await holder.destroyPromise\n }\n\n /**\n * Waits for a holder to settle (either created, destroyed, or error state).\n */\n private async waitForHolderToSettle(\n holder: InstanceHolder<any>,\n ): Promise<void> {\n switch (holder.status) {\n case InstanceStatus.Creating:\n await holder.creationPromise\n break\n case InstanceStatus.Destroying:\n await holder.destroyPromise\n break\n // Already settled states\n case InstanceStatus.Created:\n case InstanceStatus.Error:\n break\n }\n }\n\n /**\n * Clears services with dependency awareness for a specific storage.\n */\n private async clearServicesWithDependencyAwarenessForStorage(\n serviceNames: string[],\n maxRounds: number,\n storage: IHolderStorage,\n ): Promise<void> {\n const clearedServices = new Set<string>()\n let round = 1\n\n while (clearedServices.size < serviceNames.length && round <= maxRounds) {\n this.logger?.log(\n `[Invalidator] Clearing round ${round}/${maxRounds}, ${clearedServices.size}/${serviceNames.length} services cleared`,\n )\n\n // Find services that can be cleared in this round\n const servicesToClearThisRound = this.findServicesReadyForClearingInStorage(\n serviceNames,\n clearedServices,\n storage,\n )\n\n if (servicesToClearThisRound.length === 0) {\n // If no services can be cleared, try to clear remaining services anyway\n // This handles circular dependencies or other edge cases\n const remainingServices = serviceNames.filter(\n (name) => !clearedServices.has(name),\n )\n\n if (remainingServices.length > 0) {\n this.logger?.warn(\n `[Invalidator] No services ready for clearing, forcing cleanup of remaining: ${remainingServices.join(', ')}`,\n )\n await this.forceClearServicesInStorage(remainingServices, storage)\n remainingServices.forEach((name) => clearedServices.add(name))\n }\n break\n }\n\n // Clear services in this round\n const clearPromises = servicesToClearThisRound.map(\n async (serviceName) => {\n try {\n await this.invalidateWithStorage(serviceName, storage, round)\n clearedServices.add(serviceName)\n this.logger?.log(\n `[Invalidator] Successfully cleared service: ${serviceName}`,\n )\n } catch (error) {\n this.logger?.error(\n `[Invalidator] Error clearing service ${serviceName}:`,\n error,\n )\n // Still mark as cleared to avoid infinite loops\n clearedServices.add(serviceName)\n }\n },\n )\n\n await Promise.all(clearPromises)\n round++\n }\n\n if (clearedServices.size < serviceNames.length) {\n this.logger?.warn(\n `[Invalidator] Clearing completed after ${maxRounds} rounds, but ${serviceNames.length - clearedServices.size} services may not have been properly cleared`,\n )\n }\n }\n\n /**\n * Finds services that are ready to be cleared in the current round.\n * A service is ready if all its dependencies have already been cleared.\n */\n private findServicesReadyForClearingInStorage(\n allServiceNames: string[],\n clearedServices: Set<string>,\n storage: IHolderStorage,\n ): string[] {\n return allServiceNames.filter((serviceName) => {\n if (clearedServices.has(serviceName)) {\n return false // Already cleared\n }\n\n // Check if this service has any dependencies that haven't been cleared yet\n const result = storage.get(serviceName)\n if (result === null || result[0]) {\n return true // Service not found or in error state, can be cleared\n }\n\n const [, holder] = result\n // Check if all dependencies have been cleared\n const hasUnclearedDependencies = Array.from(holder!.deps).some(\n (dep) => !clearedServices.has(dep),\n )\n\n return !hasUnclearedDependencies\n })\n }\n\n /**\n * Force clears services that couldn't be cleared through normal dependency resolution.\n * This handles edge cases like circular dependencies.\n */\n private async forceClearServicesInStorage(\n serviceNames: string[],\n storage: IHolderStorage,\n ): Promise<void> {\n const promises = serviceNames.map(async (serviceName) => {\n try {\n // Directly destroy the holder without going through normal invalidation\n const result = storage.get(serviceName)\n if (result !== null && !result[0]) {\n const [, holder] = result\n await this.destroyHolderWithStorage(serviceName, holder!, storage, true)\n }\n } catch (error) {\n this.logger?.error(\n `[Invalidator] Error force clearing service ${serviceName}:`,\n error,\n )\n }\n })\n\n await Promise.all(promises)\n }\n\n /**\n * Emits events to listeners for instance lifecycle events.\n */\n private emitInstanceEvent(\n name: string,\n event: 'create' | 'destroy' = 'create',\n ) {\n if (!this.eventBus) {\n return Promise.resolve()\n }\n this.logger?.log(\n `[Invalidator]#emitInstanceEvent() Notifying listeners for ${name} with event ${event}`,\n )\n return this.eventBus.emit(name, event)\n }\n}\n","/* eslint-disable @typescript-eslint/no-empty-object-type */\n/* eslint-disable @typescript-eslint/no-unsafe-function-type */\n\ntype ListenersMap = Map<string, Map<string, Set<Function>>>\n\n/**\n * Event bus for service lifecycle events (create, destroy, etc.).\n *\n * Enables loose coupling between services by allowing them to subscribe\n * to lifecycle events of their dependencies without direct references.\n * Used primarily for invalidation cascading.\n */\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\nexport class LifecycleEventBus {\n private listeners: ListenersMap = new Map()\n constructor(private readonly logger: Console | null = null) {}\n\n on<Event extends string | `pre:${string}` | `post:${string}`>(\n ns: string,\n event: Event,\n listener: (event: Event) => void,\n ) {\n this.logger?.debug(`[LifecycleEventBus]#on(): ns:${ns} event:${event}`)\n if (!this.listeners.has(ns)) {\n this.listeners.set(ns, new Map())\n }\n\n const nsEvents = this.listeners.get(ns)!\n if (!nsEvents.has(event)) {\n nsEvents.set(event, new Set())\n }\n\n nsEvents.get(event)!.add(listener)\n\n return () => {\n nsEvents.get(event)?.delete(listener)\n if (nsEvents.get(event)?.size === 0) {\n nsEvents.delete(event)\n }\n if (nsEvents.size === 0) {\n this.listeners.delete(ns)\n }\n }\n }\n\n async emit(key: string, event: string) {\n if (!this.listeners.has(key)) {\n return\n }\n\n const events = this.listeners.get(key)!\n\n this.logger?.debug(`[LifecycleEventBus]#emit(): ${key}:${event}`)\n\n const res = await Promise.allSettled(\n [...(events.get(event) ?? [])!].map((listener) => listener(event)),\n ).then((results) => {\n const res = results\n .filter((result) => result.status === 'rejected')\n .map((result: PromiseRejectedResult) => {\n this.logger?.warn(\n `[LifecycleEventBus]#emit(): ${key}:${event} rejected with`,\n result.reason,\n )\n return result\n })\n\n if (res.length > 0) {\n return Promise.reject(res)\n }\n return results\n })\n return res\n }\n}\n","import type { InstanceHolder } from './instance-holder.mjs'\n\nimport { InjectableScope, InjectableType } from '../../enums/index.mjs'\nimport { DIError, DIErrorCode } from '../../errors/index.mjs'\nimport { BaseHolderManager } from './base-holder-manager.mjs'\nimport { InstanceStatus } from './instance-holder.mjs'\n\n/**\n * Manages the storage and retrieval of singleton instance holders.\n *\n * Provides CRUD operations and filtering for the holder map.\n * Handles holder state validation (destroying, error states) on retrieval.\n */\nexport class HolderManager extends BaseHolderManager {\n constructor(logger: Console | null = null) {\n super(logger)\n }\n\n get(\n name: string,\n ): [DIError, InstanceHolder] | [DIError] | [undefined, InstanceHolder] {\n const holder = this._holders.get(name)\n if (holder) {\n if (holder.status === InstanceStatus.Destroying) {\n this.logger?.log(\n `[HolderManager]#get() Instance ${holder.name} is destroying`,\n )\n return [DIError.instanceDestroying(holder.name), holder]\n } else if (holder.status === InstanceStatus.Error) {\n this.logger?.log(\n `[HolderManager]#get() Instance ${holder.name} is in error state`,\n )\n return [holder.instance as unknown as DIError, holder]\n }\n\n return [undefined, holder]\n } else {\n this.logger?.log(`[HolderManager]#get() Instance ${name} not found`)\n return [DIError.instanceNotFound(name)]\n }\n }\n\n set(name: string, holder: InstanceHolder): void {\n this._holders.set(name, holder)\n }\n\n has(name: string): [DIError] | [undefined, boolean] {\n const [error, holder] = this.get(name)\n if (!error) {\n return [undefined, true]\n }\n if (error.code === DIErrorCode.InstanceDestroying) {\n return [error]\n }\n return [undefined, !!holder]\n }\n\n // delete and filter methods are inherited from BaseHolderManager\n\n // createCreatingHolder method is inherited from BaseHolderManager\n\n /**\n * Creates a new holder with Created status and stores it.\n * This is useful for creating holders that already have their instance ready.\n * @param name The name of the instance\n * @param instance The actual instance to store\n * @param type The injectable type\n * @param scope The injectable scope\n * @param deps Optional set of dependencies\n * @returns The created holder\n */\n storeCreatedHolder<Instance>(\n name: string,\n instance: Instance,\n type: InjectableType,\n scope: InjectableScope,\n deps: Set<string> = new Set(),\n ): InstanceHolder<Instance> {\n const holder = this.createCreatedHolder(name, instance, type, scope, deps)\n\n this._holders.set(name, holder)\n\n return holder\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-empty-object-type */\n\nimport type { FactoryContext } from '../context/factory-context.mjs'\nimport type {\n AnyInjectableType,\n InjectionTokenType,\n} from '../../token/injection-token.mjs'\nimport type { IContainer } from '../../interfaces/container.interface.mjs'\n\nimport { DIError } from '../../errors/index.mjs'\nimport {\n BoundInjectionToken,\n FactoryInjectionToken,\n InjectionToken,\n} from '../../token/injection-token.mjs'\nimport { getInjectableToken } from '../../utils/index.mjs'\n\n/**\n * Handles token validation, normalization, and instance name generation.\n *\n * Provides utilities for resolving tokens to their underlying InjectionToken,\n * validating arguments against schemas, and generating unique instance identifiers.\n */\nexport class TokenProcessor {\n constructor(private readonly logger: Console | null = null) {}\n\n // ============================================================================\n // TOKEN NORMALIZATION\n // ============================================================================\n\n /**\n * Normalizes a token to an InjectionToken.\n * Handles class constructors by getting their injectable token.\n *\n * @param token A class constructor, InjectionToken, BoundInjectionToken, or FactoryInjectionToken\n * @returns The normalized InjectionTokenType\n */\n normalizeToken(token: AnyInjectableType): InjectionTokenType {\n if (typeof token === 'function') {\n return getInjectableToken(token)\n }\n return token as InjectionTokenType\n }\n\n /**\n * Gets the underlying \"real\" token from wrapped tokens.\n * For BoundInjectionToken and FactoryInjectionToken, returns the wrapped token.\n * For other tokens, returns the token itself.\n *\n * @param token The token to unwrap\n * @returns The underlying InjectionToken\n */\n getRealToken<T = unknown>(token: InjectionTokenType): InjectionToken<T> {\n if (\n token instanceof BoundInjectionToken ||\n token instanceof FactoryInjectionToken\n ) {\n return token.token as InjectionToken<T>\n }\n return token as InjectionToken<T>\n }\n\n /**\n * Convenience method that normalizes a token and then gets the real token.\n * Useful for checking registry entries where you need the actual registered token.\n *\n * @param token Any injectable type\n * @returns The underlying InjectionToken\n */\n getRegistryToken<T = unknown>(token: AnyInjectableType): InjectionToken<T> {\n return this.getRealToken(this.normalizeToken(token))\n }\n\n // ============================================================================\n // TOKEN VALIDATION\n // ============================================================================\n\n /**\n * Validates and resolves token arguments, handling factory token resolution and validation.\n */\n validateAndResolveTokenArgs(\n token: AnyInjectableType,\n args?: any,\n ): [\n DIError | undefined,\n { actualToken: InjectionTokenType; validatedArgs?: any },\n ] {\n let actualToken = token as InjectionToken<any, any>\n if (typeof token === 'function') {\n actualToken = getInjectableToken(token)\n }\n let realArgs = args\n if (actualToken instanceof BoundInjectionToken) {\n realArgs = actualToken.value\n } else if (actualToken instanceof FactoryInjectionToken) {\n if (actualToken.resolved) {\n realArgs = actualToken.value\n } else {\n return [DIError.factoryTokenNotResolved(token.name), { actualToken }]\n }\n }\n if (!actualToken.schema) {\n return [undefined, { actualToken, validatedArgs: realArgs }]\n }\n const validatedArgs = actualToken.schema?.safeParse(realArgs)\n if (validatedArgs && !validatedArgs.success) {\n this.logger?.error(\n `[TokenProcessor]#validateAndResolveTokenArgs(): Error validating args for ${actualToken.name.toString()}`,\n validatedArgs.error,\n )\n return [DIError.unknown(validatedArgs.error), { actualToken }]\n }\n return [undefined, { actualToken, validatedArgs: validatedArgs?.data }]\n }\n\n /**\n * Generates a unique instance name based on token and arguments.\n */\n generateInstanceName(token: InjectionTokenType, args: any): string {\n if (!args) {\n return token.toString()\n }\n\n const formattedArgs = Object.entries(args)\n .sort(([keyA], [keyB]) => keyA.localeCompare(keyB))\n .map(([key, value]) => `${key}=${this.formatArgValue(value)}`)\n .join(',')\n\n return `${token.toString()}:${formattedArgs.replaceAll(/\"/g, '').replaceAll(/:/g, '=')}`\n }\n\n /**\n * Formats a single argument value for instance name generation.\n */\n formatArgValue(value: any): string {\n if (typeof value === 'function') {\n return `fn_${value.name}(${value.length})`\n }\n if (typeof value === 'symbol') {\n return value.toString()\n }\n return JSON.stringify(value).slice(0, 40)\n }\n\n /**\n * Creates a factory context for dependency injection during service instantiation.\n * @param container The container instance (Container or ScopedContainer) for dependency resolution\n * @param onDependencyResolved Callback when a dependency is resolved, receives the instance name\n */\n createFactoryContext(\n container: IContainer,\n onDependencyResolved?: (instanceName: string) => void,\n ): FactoryContext & {\n getDestroyListeners: () => (() => void)[]\n deps: Set<string>\n } {\n const destroyListeners = new Set<() => void>()\n const deps = new Set<string>()\n\n function addDestroyListener(listener: () => void) {\n destroyListeners.add(listener)\n }\n\n function getDestroyListeners() {\n return Array.from(destroyListeners)\n }\n\n const self = this\n\n return {\n // @ts-expect-error This is correct type\n async inject(token, args) {\n // Get the instance name for dependency tracking\n const actualToken =\n typeof token === 'function' ? getInjectableToken(token) : token\n const instanceName = self.generateInstanceName(actualToken, args)\n deps.add(instanceName)\n\n if (onDependencyResolved) {\n onDependencyResolved(instanceName)\n }\n\n // Use the container's get method for resolution\n return container.get(token, args)\n },\n addDestroyListener,\n getDestroyListeners,\n container,\n deps,\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-empty-object-type */\nimport type { z, ZodObject, ZodOptional } from 'zod/v4'\n\nimport type {\n AnyInjectableType,\n InjectionTokenSchemaType,\n} from '../../token/injection-token.mjs'\nimport type { IContainer } from '../../interfaces/container.interface.mjs'\nimport type { Registry } from '../../token/registry.mjs'\nimport type { ScopedContainer } from '../../container/scoped-container.mjs'\nimport type { ClearAllOptions } from './invalidator.mjs'\nimport type { Injectors } from '../../utils/index.mjs'\n\nimport { defaultInjectors } from '../../injectors.mjs'\nimport { InstanceResolver } from './instance-resolver.mjs'\nimport { globalRegistry } from '../../token/registry.mjs'\nimport { Instantiator } from './instantiator.mjs'\nimport { Invalidator } from './invalidator.mjs'\nimport { LifecycleEventBus } from '../lifecycle/lifecycle-event-bus.mjs'\nimport { HolderManager } from '../holder/holder-manager.mjs'\nimport { TokenProcessor } from './token-processor.mjs'\n\n/**\n * Core DI engine that coordinates service instantiation, resolution, and lifecycle.\n *\n * Acts as the central orchestrator for dependency injection operations,\n * delegating to specialized components (InstanceResolver, Instantiator, Invalidator)\n * for specific tasks.\n */\nexport class ServiceLocator {\n private readonly eventBus: LifecycleEventBus\n private readonly manager: HolderManager\n private readonly instantiator: Instantiator\n private readonly tokenProcessor: TokenProcessor\n private readonly invalidator: Invalidator\n private readonly instanceResolver: InstanceResolver\n\n constructor(\n private readonly registry: Registry = globalRegistry,\n private readonly logger: Console | null = null,\n private readonly injectors: Injectors = defaultInjectors,\n ) {\n this.eventBus = new LifecycleEventBus(logger)\n this.manager = new HolderManager(logger)\n this.instantiator = new Instantiator(injectors)\n this.tokenProcessor = new TokenProcessor(logger)\n this.invalidator = new Invalidator(\n this.manager,\n this.eventBus,\n logger,\n )\n this.instanceResolver = new InstanceResolver(\n this.registry,\n this.manager,\n this.instantiator,\n this.tokenProcessor,\n logger,\n this,\n )\n }\n\n // ============================================================================\n // PUBLIC METHODS\n // ============================================================================\n\n getEventBus() {\n return this.eventBus\n }\n\n getManager() {\n return this.manager\n }\n\n getInvalidator() {\n return this.invalidator\n }\n\n getTokenProcessor() {\n return this.tokenProcessor\n }\n\n public getInstanceIdentifier(token: AnyInjectableType, args?: any): string {\n const [err, { actualToken, validatedArgs }] =\n this.tokenProcessor.validateAndResolveTokenArgs(token, args)\n if (err) {\n throw err\n }\n return this.tokenProcessor.generateInstanceName(actualToken, validatedArgs)\n }\n\n /**\n * Gets or creates an instance for the given token.\n * @param token The injection token\n * @param args Optional arguments\n * @param contextContainer The container to use for creating FactoryContext\n */\n public async getInstance(\n token: AnyInjectableType,\n args: any,\n contextContainer: IContainer,\n ) {\n const [err, data] = await this.instanceResolver.resolveInstance(\n token,\n args,\n contextContainer,\n )\n if (err) {\n return [err]\n }\n\n return [undefined, data]\n }\n\n /**\n * Gets or throws an instance for the given token.\n * @param token The injection token\n * @param args Optional arguments\n * @param contextContainer The container to use for creating FactoryContext\n */\n public async getOrThrowInstance<Instance>(\n token: AnyInjectableType,\n args: any,\n contextContainer: IContainer,\n ): Promise<Instance> {\n const [error, instance] = await this.getInstance(token, args, contextContainer)\n if (error) {\n throw error\n }\n return instance\n }\n\n /**\n * Resolves a request-scoped service for a ScopedContainer.\n * The service will be stored in the ScopedContainer's request context.\n *\n * @param token The injection token\n * @param args Optional arguments\n * @param scopedContainer The ScopedContainer that owns the request context\n */\n public async resolveRequestScoped(\n token: AnyInjectableType,\n args: any,\n scopedContainer: ScopedContainer,\n ): Promise<any> {\n const [err, data] = await this.instanceResolver.resolveRequestScopedInstance(\n token,\n args,\n scopedContainer,\n )\n if (err) {\n throw err\n }\n return data\n }\n\n public getSyncInstance<\n Instance,\n Schema extends InjectionTokenSchemaType | undefined,\n >(\n token: AnyInjectableType,\n args: Schema extends ZodObject\n ? z.input<Schema>\n : Schema extends ZodOptional<ZodObject>\n ? z.input<Schema> | undefined\n : undefined,\n contextContainer: IContainer,\n ): Instance | null {\n return this.instanceResolver.getSyncInstance(token, args as any, contextContainer)\n }\n\n invalidate(service: string, round = 1): Promise<any> {\n return this.invalidator.invalidate(service, round)\n }\n\n /**\n * Gracefully clears all services in the ServiceLocator using invalidation logic.\n * This method respects service dependencies and ensures proper cleanup order.\n * Services that depend on others will be invalidated first, then their dependencies.\n *\n * @param options Optional configuration for the clearing process\n * @returns Promise that resolves when all services have been cleared\n */\n async clearAll(options: ClearAllOptions = {}): Promise<void> {\n return this.invalidator.clearAll(options)\n }\n\n /**\n * Waits for all services to settle (either created, destroyed, or error state).\n */\n async ready(): Promise<void> {\n return this.invalidator.ready()\n }\n\n /**\n * Helper method for InstanceResolver to generate instance names.\n * This is needed for the factory context creation.\n */\n generateInstanceName(token: any, args: any): string {\n return this.tokenProcessor.generateInstanceName(token, args)\n }\n}\n","import type { z, ZodType } from 'zod/v4'\n\nimport type {\n ClassType,\n ClassTypeWithArgument,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '../token/injection-token.mjs'\nimport type { IContainer } from '../interfaces/container.interface.mjs'\nimport type { Factorable } from '../interfaces/factory.interface.mjs'\nimport type { Registry } from '../token/registry.mjs'\nimport type { InstanceHolder } from '../internal/holder/instance-holder.mjs'\nimport type { Injectors } from '../utils/index.mjs'\nimport type { Join, UnionToArray } from '../utils/types.mjs'\n\nimport { Injectable } from '../decorators/injectable.decorator.mjs'\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\nimport { DIError } from '../errors/index.mjs'\nimport {\n BoundInjectionToken,\n FactoryInjectionToken,\n} from '../token/injection-token.mjs'\nimport { defaultInjectors } from '../injectors.mjs'\nimport { globalRegistry } from '../token/registry.mjs'\nimport { ScopedContainer } from './scoped-container.mjs'\nimport { ServiceLocator } from '../internal/core/service-locator.mjs'\nimport { getInjectableToken } from '../utils/get-injectable-token.mjs'\n\n/**\n * Main dependency injection container.\n *\n * Provides a simplified public API for dependency injection, wrapping\n * a ServiceLocator instance. Handles singleton and transient services directly,\n * while request-scoped services require using beginRequest() to create a ScopedContainer.\n */\n@Injectable()\nexport class Container implements IContainer {\n private readonly serviceLocator: ServiceLocator\n private readonly activeRequestIds = new Set<string>()\n\n constructor(\n protected readonly registry: Registry = globalRegistry,\n protected readonly logger: Console | null = null,\n protected readonly injectors: Injectors = defaultInjectors,\n ) {\n this.serviceLocator = new ServiceLocator(registry, logger, injectors)\n this.registerSelf()\n }\n\n private registerSelf() {\n const token = getInjectableToken(Container)\n const instanceName = this.serviceLocator.getInstanceIdentifier(token)\n this.serviceLocator\n .getManager()\n .storeCreatedHolder(\n instanceName,\n this,\n InjectableType.Class,\n InjectableScope.Singleton,\n )\n }\n\n /**\n * Gets an instance from the container.\n * This method has the same type signature as the inject method from get-injectors.mts\n *\n * NOTE: Request-scoped services cannot be resolved directly from Container.\n * Use beginRequest() to create a ScopedContainer for request-scoped services.\n */\n // #1 Simple class\n get<T extends ClassType>(\n token: T,\n ): InstanceType<T> extends Factorable<infer R>\n ? Promise<R>\n : Promise<InstanceType<T>>\n // #1.1 Simple class with args\n get<T extends ClassTypeWithArgument<R>, R>(\n token: T,\n args: R,\n ): Promise<InstanceType<T>>\n\n // #2 Token with required Schema\n get<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n ): Promise<T>\n // #3 Token with optional Schema\n get<T, S extends InjectionTokenSchemaType, R extends boolean>(\n token: InjectionToken<T, S, R>,\n ): R extends false\n ? Promise<T>\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<\n UnionToArray<keyof Type>,\n ', '\n >}`\n : 'Error: Your token requires args'\n // #4 Token with no Schema\n get<T>(token: InjectionToken<T, undefined>): Promise<T>\n get<T>(token: BoundInjectionToken<T, any>): Promise<T>\n get<T>(token: FactoryInjectionToken<T, any>): Promise<T>\n\n async get(\n token:\n | ClassType\n | InjectionToken<any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args?: unknown,\n ) {\n // Check if this is a request-scoped service\n // Use TokenProcessor for consistent token normalization\n const tokenProcessor = this.serviceLocator.getTokenProcessor()\n const realToken = tokenProcessor.getRegistryToken(token)\n\n if (this.registry.has(realToken)) {\n const record = this.registry.get(realToken)\n if (record.scope === InjectableScope.Request) {\n throw DIError.unknown(\n `Cannot resolve request-scoped service \"${String(realToken.name)}\" from Container. ` +\n `Use beginRequest() to create a ScopedContainer for request-scoped services.`,\n )\n }\n }\n\n return this.serviceLocator.getOrThrowInstance(token, args as any, this)\n }\n\n /**\n * Gets an instance with a specific container context.\n * Used by ScopedContainer to delegate singleton/transient resolution\n * while maintaining the correct container context for nested inject() calls.\n *\n * @internal\n */\n async getWithContext(\n token:\n | ClassType\n | InjectionToken<any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args: unknown,\n contextContainer: IContainer,\n ): Promise<any> {\n return this.serviceLocator.getOrThrowInstance(\n token,\n args as any,\n contextContainer,\n )\n }\n\n /**\n * Resolves a request-scoped service for a ScopedContainer.\n * The service will be stored in the ScopedContainer's request context.\n *\n * @internal\n */\n async resolveForRequest(\n token:\n | ClassType\n | InjectionToken<any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args: unknown,\n scopedContainer: ScopedContainer,\n ): Promise<any> {\n return this.serviceLocator.resolveRequestScoped(\n token,\n args as any,\n scopedContainer,\n )\n }\n\n /**\n * Gets the underlying ServiceLocator instance for advanced usage\n */\n getServiceLocator(): ServiceLocator {\n return this.serviceLocator\n }\n\n /**\n * Gets the registry\n */\n getRegistry(): Registry {\n return this.registry\n }\n\n /**\n * Invalidates a service and its dependencies\n */\n async invalidate(service: unknown): Promise<void> {\n const holder = this.getHolderByInstance(service)\n if (holder) {\n await this.serviceLocator.invalidate(holder.name)\n }\n }\n\n /**\n * Gets a service holder by instance (reverse lookup)\n */\n private getHolderByInstance(\n instance: unknown,\n ): InstanceHolder | null {\n const holderMap = Array.from(\n this.serviceLocator\n .getManager()\n .filter((holder) => holder.instance === instance)\n .values(),\n )\n\n return holderMap.length > 0 ? holderMap[0] : null\n }\n\n /**\n * Checks if a service is registered in the container\n */\n isRegistered(token: any): boolean {\n try {\n return this.serviceLocator.getInstanceIdentifier(token) !== null\n } catch {\n return false\n }\n }\n\n /**\n * Disposes the container and cleans up all resources\n */\n async dispose(): Promise<void> {\n await this.serviceLocator.clearAll()\n }\n\n /**\n * Waits for all pending operations to complete\n */\n async ready(): Promise<void> {\n await this.serviceLocator.ready()\n }\n\n /**\n * @internal\n * Attempts to get an instance synchronously if it already exists.\n * Returns null if the instance doesn't exist or is not ready.\n */\n tryGetSync<T>(token: any, args?: any): T | null {\n return this.serviceLocator.getSyncInstance(token, args, this)\n }\n\n // ============================================================================\n // REQUEST CONTEXT MANAGEMENT\n // ============================================================================\n\n /**\n * Begins a new request context and returns a ScopedContainer.\n *\n * The ScopedContainer provides isolated request-scoped service resolution\n * while delegating singleton and transient services to this Container.\n *\n * @param requestId Unique identifier for this request\n * @param metadata Optional metadata for the request\n * @param priority Priority for resolution (higher = more priority)\n * @returns A ScopedContainer for this request\n */\n beginRequest(\n requestId: string,\n metadata?: Record<string, any>,\n priority: number = 100,\n ): ScopedContainer {\n if (this.activeRequestIds.has(requestId)) {\n throw DIError.unknown(\n `Request context \"${requestId}\" already exists. Use a unique request ID.`,\n )\n }\n\n this.activeRequestIds.add(requestId)\n\n this.logger?.log(`[Container] Started request context: ${requestId}`)\n\n return new ScopedContainer(\n this,\n this.registry,\n requestId,\n metadata,\n priority,\n )\n }\n\n /**\n * Removes a request ID from the active set.\n * Called by ScopedContainer when the request ends.\n *\n * @internal\n */\n removeActiveRequest(requestId: string): void {\n this.activeRequestIds.delete(requestId)\n this.logger?.log(`[Container] Ended request context: ${requestId}`)\n }\n\n /**\n * Gets the set of active request IDs.\n */\n getActiveRequestIds(): ReadonlySet<string> {\n return this.activeRequestIds\n }\n\n /**\n * Checks if a request ID is currently active.\n */\n hasActiveRequest(requestId: string): boolean {\n return this.activeRequestIds.has(requestId)\n }\n\n /**\n * Clears all instances and bindings from the container.\n * This is useful for testing or resetting the container state.\n */\n clear(): Promise<void> {\n return this.serviceLocator.clearAll()\n }\n}\n","import type {\n ClassTypeWithInstance,\n InjectionTokenSchemaType,\n} from '../token/injection-token.mjs'\nimport type { Factorable, FactorableWithArgs } from '../interfaces/index.mjs'\nimport type { Registry } from '../token/registry.mjs'\n\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\nimport { InjectionToken } from '../token/injection-token.mjs'\nimport { globalRegistry } from '../token/registry.mjs'\nimport { InjectableTokenMeta } from '../symbols/index.mjs'\n\nexport interface FactoryOptions {\n scope?: InjectableScope\n token?: InjectionToken<any, any>\n registry?: Registry\n}\n\n// #1 Factory without arguments\nexport function Factory<R>(options?: {\n scope?: InjectableScope\n registry?: Registry\n}): <T extends ClassTypeWithInstance<Factorable<R>>>(\n target: T,\n context?: ClassDecoratorContext,\n) => T\n\n// #2 Factory with typed token\nexport function Factory<R, S>(options: {\n scope?: InjectableScope\n token: InjectionToken<R, S>\n registry?: Registry\n}): R extends undefined // #2.1 Check that token has a type\n ? never // #2.1.1 Token must have a type\n : S extends InjectionTokenSchemaType // #2.2 Check that schema is an object or a record\n ? <T extends ClassTypeWithInstance<FactorableWithArgs<R, S>>>( // #2.2.1 Token have a schema\n target: T,\n context?: ClassDecoratorContext,\n ) => T\n : S extends undefined // #2.3 For a factory without schema\n ? <T extends ClassTypeWithInstance<Factorable<R>>>( // #2.3.1 Token without a schema\n target: T,\n context?: ClassDecoratorContext,\n ) => T\n : never // #2.4 Cannot use a token without a type and schema\n\nexport function Factory({\n scope = InjectableScope.Singleton,\n token,\n registry = globalRegistry,\n}: FactoryOptions = {}) {\n return <\n T extends ClassTypeWithInstance<\n Factorable<any> | FactorableWithArgs<any, any>\n >,\n >(\n target: T,\n context?: ClassDecoratorContext,\n ): T => {\n if (\n (context && context.kind !== 'class') ||\n (target instanceof Function && !context)\n ) {\n throw new Error(\n '[ServiceLocator] @Factory decorator can only be used on classes.',\n )\n }\n\n let injectableToken: InjectionToken<any, any> =\n token ?? InjectionToken.create(target)\n\n registry.set(injectableToken, scope, target, InjectableType.Factory)\n\n // @ts-expect-error\n target[InjectableTokenMeta] = injectableToken\n\n return target\n }\n}\n","/* eslint-disable @typescript-eslint/no-non-null-assertion */\n/* eslint-disable @typescript-eslint/no-empty-object-type */\n/* eslint-disable @typescript-eslint/no-unsafe-function-type */\n\nimport { Injectable, InjectableScope } from './index.mjs'\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport type EventsConfig = {\n [event: string]: any[]\n}\nexport type EventsNames<Events extends EventsConfig> = Exclude<\n keyof Events,\n symbol | number\n>\nexport type EventsArgs<\n Events extends EventsConfig,\n Name extends EventsNames<Events>,\n> = Events[Name] extends any[] ? Events[Name] : []\n\nexport type ChannelEmitter<\n Events extends EventsConfig,\n Ns extends string,\n E extends EventsNames<Events>,\n> = {\n emit<Args extends EventsArgs<Events, E>>(\n ns: Ns,\n event: E,\n ...args: Args\n ): Promise<any>\n}\n\nexport interface EventEmitterInterface<Events extends EventsConfig> {\n on<E extends EventsNames<Events>, Args extends EventsArgs<Events, E>>(\n event: E,\n listener: (...args: Args) => void | Promise<void>,\n ): () => void\n emit<E extends EventsNames<Events>, Args extends EventsArgs<Events, E>>(\n event: E,\n ...args: Args\n ): void | Promise<void>\n}\n\n@Injectable({ scope: InjectableScope.Transient })\nexport class EventEmitter<Events extends EventsConfig = {}>\n implements EventEmitterInterface<Events>\n{\n private listeners: Map<EventsNames<Events>, Set<Function>> = new Map()\n\n on<E extends EventsNames<Events>, Args extends EventsArgs<Events, E>>(\n event: E,\n listener: (...args: Args) => void | Promise<void>,\n ) {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n\n this.listeners.get(event)!.add(listener)\n\n return () => {\n this.off(event, listener)\n }\n }\n\n off<E extends EventsNames<Events>, Args extends EventsArgs<Events, E>>(\n event: E,\n listener: (...args: Args) => void | Promise<void>,\n ) {\n if (!this.listeners.has(event)) {\n return\n }\n\n this.listeners.get(event)!.delete(listener)\n if (this.listeners.get(event)!.size === 0) {\n this.listeners.delete(event)\n }\n }\n\n once<E extends EventsNames<Events>, Args extends EventsArgs<Events, E>>(\n event: E,\n listener: (...args: Args) => void | Promise<void>,\n ) {\n const off = this.on(event, (...args) => {\n off()\n // @ts-expect-error - This is a valid call\n listener(...args)\n })\n\n return off\n }\n\n async emit<E extends EventsNames<Events>, Args extends EventsArgs<Events, E>>(\n event: E,\n ...args: Args\n ): Promise<any> {\n if (!this.listeners.has(event)) {\n return\n }\n\n return Promise.all(\n Array.from(this.listeners.get(event)!).map((listener) =>\n listener(...args),\n ),\n )\n }\n}\n"],"mappings":"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"}
|