{"version":3,"file":"instance-resolver.mjs","names":["InjectableScope","DIError","DIErrorCode","FactoryInjectionToken","getCurrentResolutionContext","withResolutionContext","InstanceStatus","CircularDetector","InstanceResolver","registry","storage","serviceInitializer","tokenResolver","nameResolver","scopeTracker","serviceInvalidator","eventBus","logger","resolveInstance","token","args","contextContainer","requestStorage","requestId","resolveWithStorage","undefined","resolveRequestScopedInstance","scopedContainer","getParent","getStorage","getRequestId","err","data","resolveTokenAndPrepareInstanceName","instanceName","validatedArgs","realToken","scope","getResult","get","getHolder","name","result","reqResult","error","holder","resolutionCtx","waiterHolder","readyResult","waitForInstanceReady","instance","handledResult","handleStorageError","createError","createAndStoreInstance","actualToken","validateAndResolveTokenArgs","code","TokenValidationError","FactoryTokenNotResolved","log","factoryCtx","inject","t","a","container","addDestroyListener","resolve","getRealToken","record","generateInstanceName","InstanceDestroying","destroyPromise","newResult","delete","has","factoryNotFound","toString","type","recordScope","serviceScope","Transient","createTransientInstance","Request","initializationError","storageToUse","deferred","createHolder","Set","set","ctx","createServiceInitializationContext","deps","destroyListeners","getDestroyListeners","instantiateService","then","length","newScope","newName","handleInstantiationResult","catch","handleInstantiationError","originalToken","tempHolder","status","Created","creationPromise","dependencies","createdAt","Date","now","waitingFor","handleInstantiationSuccess","_scopedContainer","_requestId","storageForSubscriptions","size","setupDependencySubscriptions","Error","unknown","reject","Creating","cycle","detectCycle","circularDependency","process","env","NODE_ENV","add","Destroying","instanceDestroying","instanceNotFound","serviceName","serviceToken","normalizeToken","depRecord","depScope","dependencyRequestId","finalDepName","Singleton","needsUpgrade","newServiceName","checkAndUpgradeScope","listener","push","trackDependency"],"sources":["../../../../src/internal/core/instance-resolver.mts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { ScopedContainer } from '../../container/scoped-container.mjs'\nimport type { IContainer } from '../../interfaces/container.interface.mjs'\nimport type {\n  AnyInjectableType,\n  InjectionTokenType,\n} from '../../token/injection-token.mjs'\nimport type { Registry } from '../../token/registry.mjs'\nimport type { ServiceInitializationContext } from '../context/service-initialization-context.mjs'\nimport type { IHolderStorage } from '../holder/holder-storage.interface.mjs'\nimport type { InstanceHolder } from '../holder/instance-holder.mjs'\nimport type { LifecycleEventBus } from '../lifecycle/lifecycle-event-bus.mjs'\n\nimport { InjectableScope } from '../../enums/index.mjs'\nimport { DIError, DIErrorCode } from '../../errors/index.mjs'\nimport {\n  FactoryInjectionToken,\n  InjectionToken,\n} from '../../token/injection-token.mjs'\nimport {\n  getCurrentResolutionContext,\n  withResolutionContext,\n} from '../context/resolution-context.mjs'\nimport { InstanceStatus } from '../holder/instance-holder.mjs'\nimport { CircularDetector } from '../lifecycle/circular-detector.mjs'\nimport { NameResolver } from './name-resolver.mjs'\nimport { ScopeTracker } from './scope-tracker.mjs'\nimport { ServiceInitializer } from './service-initializer.mjs'\nimport { ServiceInvalidator } from './service-invalidator.mjs'\nimport { TokenResolver } from './token-resolver.mjs'\n\n/**\n * Resolves instances from tokens, handling caching, creation, and scope rules.\n *\n * Uses unified storage for both singleton and request-scoped services.\n * Coordinates with ServiceInitializer for actual service creation.\n * Integrates ScopeTracker for automatic scope upgrades.\n */\nexport class InstanceResolver {\n  constructor(\n    private readonly registry: Registry,\n    private readonly storage: IHolderStorage,\n    private readonly serviceInitializer: ServiceInitializer,\n    private readonly tokenResolver: TokenResolver,\n    private readonly nameResolver: NameResolver,\n    private readonly scopeTracker: ScopeTracker,\n    private readonly serviceInvalidator: ServiceInvalidator,\n    private readonly eventBus: LifecycleEventBus,\n    private readonly logger: Console | null = null,\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 context\n   * @param requestStorage Optional request storage (for scope upgrades)\n   * @param requestId Optional request ID (for scope upgrades)\n   */\n  async resolveInstance(\n    token: AnyInjectableType,\n    args: any,\n    contextContainer: IContainer,\n    requestStorage?: IHolderStorage,\n    requestId?: string,\n  ): Promise<[undefined, any] | [DIError]> {\n    return this.resolveWithStorage(\n      token,\n      args,\n      contextContainer,\n      this.storage,\n      undefined,\n      requestStorage,\n      requestId,\n    )\n  }\n\n  /**\n   * Resolves a request-scoped instance for a ScopedContainer.\n   * The service will be stored in the ScopedContainer's request storage.\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    return this.resolveWithStorage(\n      token,\n      args,\n      scopedContainer.getParent(),\n      scopedContainer.getParent().getStorage(),\n      scopedContainer,\n      scopedContainer.getStorage(),\n      scopedContainer.getRequestId(),\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 context\n   * @param storage The storage strategy to use\n   * @param scopedContainer Optional scoped container for request-scoped services\n   * @param requestStorage Optional request storage (for scope upgrades)\n   * @param requestId Optional request ID (for scope upgrades)\n   */\n  private async resolveWithStorage(\n    token: AnyInjectableType,\n    args: any,\n    contextContainer: IContainer,\n    storage: IHolderStorage,\n    scopedContainer?: ScopedContainer,\n    requestStorage?: IHolderStorage,\n    requestId?: string,\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      requestId,\n      scopedContainer,\n    )\n    if (err) {\n      return [err]\n    }\n\n    const { instanceName, validatedArgs, realToken, scope } = 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 =\n      storage.get(instanceName) ?? requestStorage?.get(instanceName) ?? null\n\n    // Create getHolder function for circular dependency detection\n    const getHolder = (name: string): InstanceHolder | undefined => {\n      // Check both storages\n      const result = storage.get(name)\n      if (result && result[0] === undefined && result[1]) {\n        return result[1]\n      }\n      if (requestStorage) {\n        const reqResult = requestStorage.get(name)\n        if (reqResult && reqResult[0] === undefined && reqResult[1]) {\n          return reqResult[1]\n        }\n      }\n      return undefined\n    }\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        // Try to get waiterHolder from resolution context if available\n        const resolutionCtx = getCurrentResolutionContext()\n        const waiterHolder = resolutionCtx?.waiterHolder\n        const readyResult = await this.waitForInstanceReady(\n          holder,\n          waiterHolder,\n          getHolder,\n        )\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      requestStorage,\n      requestId,\n      scope,\n    )\n    if (createError) {\n      return [createError]\n    }\n\n    return [undefined, holder!.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    requestId?: string,\n    scopedContainer?: ScopedContainer,\n  ): Promise<\n    | [\n        undefined,\n        {\n          instanceName: string\n          validatedArgs: any\n          actualToken: InjectionTokenType\n          realToken: InjectionToken<any, any>\n          scope: InjectableScope\n        },\n      ]\n    | [DIError]\n  > {\n    const [err, { actualToken, validatedArgs }] =\n      this.tokenResolver.validateAndResolveTokenArgs(token, args)\n    if (\n      err instanceof DIError &&\n      err.code === DIErrorCode.TokenValidationError\n    ) {\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      // Create a simple factory context for resolving the factory token\n      const factoryCtx = {\n        inject: async (t: any, a?: any) =>\n          (scopedContainer ?? contextContainer).get(t, a),\n        container: scopedContainer ?? contextContainer,\n        addDestroyListener: () => {},\n      }\n      await actualToken.resolve(factoryCtx as any)\n      return this.resolveTokenAndPrepareInstanceName(\n        token,\n        undefined,\n        contextContainer,\n        requestId,\n        scopedContainer,\n      )\n    }\n\n    // Get the real token for registry lookup\n    const realToken = this.tokenResolver.getRealToken(actualToken)\n    // Get scope from registry\n    const record = this.registry.get(realToken)\n    const scope = record.scope\n\n    // Generate instance name with requestId if needed\n    const instanceName = this.nameResolver.generateInstanceName(\n      actualToken,\n      validatedArgs,\n      requestId,\n      scope,\n    )\n\n    return [\n      undefined,\n      { instanceName, validatedArgs, actualToken, realToken, scope },\n    ]\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          // Create getHolder for circular dependency detection\n          const getHolder = (name: string): InstanceHolder | undefined => {\n            const result = storage.get(name)\n            return result && result[0] === undefined && result[1]\n              ? result[1]\n              : undefined\n          }\n          const readyResult = await this.waitForInstanceReady(\n            newResult[1]!,\n            undefined,\n            getHolder,\n          )\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    requestStorage?: IHolderStorage,\n    requestId?: string,\n    scope?: InjectableScope,\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 record = this.registry.get<Instance, any>(realToken)\n    const { type, scope: recordScope } = record\n    const serviceScope = scope || recordScope\n\n    // For transient services, don't use storage locking - create directly\n    if (serviceScope === InjectableScope.Transient) {\n      return this.createTransientInstance(\n        instanceName,\n        record,\n        args,\n        contextContainer,\n        scopedContainer,\n        requestStorage,\n        requestId,\n      )\n    }\n    if (serviceScope === InjectableScope.Request && !requestStorage) {\n      return [\n        DIError.initializationError(\n          `Request storage is required for request-scoped services`,\n          instanceName,\n        ),\n      ]\n    }\n\n    let storageToUse: IHolderStorage\n    if (serviceScope === InjectableScope.Request) {\n      storageToUse = requestStorage!\n    } else {\n      storageToUse = storage\n    }\n\n    // Create holder in \"Creating\" state\n    const [deferred, holder] = storageToUse.createHolder<Instance>(\n      instanceName,\n      type,\n      new Set(),\n    )\n    // Store holder immediately (for lock mechanism)\n    storageToUse.set(instanceName, holder)\n\n    // Create context for service initialization\n    const ctx = this.createServiceInitializationContext(\n      scopedContainer ?? contextContainer,\n      instanceName,\n      serviceScope,\n      holder.deps,\n      realToken,\n      requestStorage,\n      requestId,\n    )\n\n    holder.destroyListeners = ctx.getDestroyListeners()\n\n    // Create getHolder function for resolution context\n    const getHolder = (name: string): InstanceHolder | undefined => {\n      // Check both storages\n      const result = storage.get(name)\n      if (result && result[0] === undefined && result[1]) {\n        return result[1]\n      }\n      if (requestStorage) {\n        const reqResult = requestStorage.get(name)\n        if (reqResult && reqResult[0] === undefined && reqResult[1]) {\n          return reqResult[1]\n        }\n      }\n      return undefined\n    }\n\n    // Start async instantiation within resolution context for circular dependency detection\n    withResolutionContext(holder, getHolder, () => {\n      this.serviceInitializer\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          const newScope = record.scope\n          const newName = this.nameResolver.generateInstanceName(\n            realToken,\n            args,\n            requestId,\n            newScope,\n          )\n          await this.handleInstantiationResult(\n            newName,\n            holder,\n            ctx,\n            deferred,\n            newScope,\n            error,\n            instance,\n            scopedContainer,\n            requestStorage,\n            requestId,\n          )\n        })\n        .catch(async (error: Error) => {\n          const newScope = record.scope\n          const newName = this.nameResolver.generateInstanceName(\n            realToken,\n            args,\n            requestId,\n            newScope,\n          )\n\n          await this.handleInstantiationError(\n            newName,\n            holder,\n            deferred,\n            newScope,\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    // Use resolution context to get waiterHolder if available\n    const resolutionCtx = getCurrentResolutionContext()\n    const waiterHolder = resolutionCtx?.waiterHolder\n    return this.waitForInstanceReady(holder, waiterHolder, getHolder)\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    contextContainer: IContainer,\n    scopedContainer?: ScopedContainer,\n    requestStorage?: IHolderStorage,\n    requestId?: string,\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 ctx = this.createServiceInitializationContext(\n      scopedContainer ?? contextContainer,\n      instanceName,\n      InjectableScope.Transient,\n      new Set(),\n      record.originalToken,\n      requestStorage,\n      requestId,\n    )\n\n    const [error, instance] = await this.serviceInitializer.instantiateService(\n      ctx,\n      record,\n      args,\n    )\n\n    if (error) {\n      return [error]\n    }\n\n    // Create a temporary holder for the result\n    const tempHolder: 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.dependencies,\n      destroyListeners: ctx.getDestroyListeners(),\n      createdAt: Date.now(),\n      waitingFor: new Set(),\n    }\n\n    return [undefined, tempHolder]\n  }\n\n  /**\n   * Handles successful service instantiation.\n   */\n  private async handleInstantiationSuccess(\n    instanceName: string,\n    holder: InstanceHolder<any>,\n    ctx: ServiceInitializationContext,\n    deferred: any,\n    instance: any,\n    _scopedContainer?: ScopedContainer,\n    requestStorage?: IHolderStorage,\n    _requestId?: string,\n  ): Promise<void> {\n    holder.instance = instance\n    holder.status = InstanceStatus.Created\n\n    // Set up dependency subscriptions for event-based invalidation\n    // Determine which storage to use for subscriptions\n    const storageForSubscriptions = requestStorage || this.storage\n\n    // Set up subscriptions via ServiceInvalidator\n    if (ctx.dependencies.size > 0) {\n      this.serviceInvalidator.setupDependencySubscriptions(\n        instanceName,\n        ctx.dependencies,\n        storageForSubscriptions,\n        holder,\n      )\n    }\n\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    holder.status = InstanceStatus.Error\n    holder.instance = error instanceof DIError ? error : DIError.unknown(error)\n    this.logger?.error(\n      `[InstanceResolver] Instance ${instanceName} creation failed:`,\n      error,\n    )\n    deferred.reject(error instanceof DIError ? error : DIError.unknown(error))\n  }\n\n  /**\n   * Handles instantiation result (success or error).\n   */\n  private async handleInstantiationResult(\n    instanceName: string,\n    holder: InstanceHolder<any>,\n    ctx: ServiceInitializationContext,\n    deferred: any,\n    scope: InjectableScope,\n    error: any,\n    instance: any,\n    scopedContainer?: ScopedContainer,\n    requestStorage?: IHolderStorage,\n    requestId?: string,\n  ): Promise<void> {\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        requestStorage,\n        requestId,\n      )\n    }\n  }\n\n  /**\n   * Waits for an instance holder to be ready and returns the appropriate result.\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   */\n  private async waitForInstanceReady<T>(\n    holder: InstanceHolder<T>,\n    waiterHolder?: InstanceHolder,\n    getHolder?: (name: string) => InstanceHolder | undefined,\n  ): Promise<[undefined, InstanceHolder<T>] | [DIError]> {\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          if (process.env.NODE_ENV !== 'production') {\n            // Track the waiting relationship\n            waiterHolder.waitingFor.add(holder.name)\n          }\n        }\n\n        try {\n          await holder.creationPromise\n        } finally {\n          if (process.env.NODE_ENV !== 'production') {\n            // Clean up the waiting relationship\n            if (waiterHolder) {\n              waiterHolder.waitingFor.delete(holder.name)\n            }\n          }\n        }\n\n        // Recursively check after creation completes\n        return this.waitForInstanceReady(holder, waiterHolder, getHolder)\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        // @ts-expect-error Maybe we will use this in the future\n        return [DIError.instanceNotFound(holder?.name ?? 'unknown')]\n    }\n  }\n\n  /**\n   * Creates a ServiceInitializationContext for service instantiation.\n   */\n  private createServiceInitializationContext(\n    container: IContainer,\n    serviceName: string,\n    scope: InjectableScope,\n    deps: Set<string>,\n    serviceToken: InjectionToken<any, any>,\n    requestStorage?: IHolderStorage,\n    requestId?: string,\n  ): ServiceInitializationContext {\n    const destroyListeners: Array<() => void> = []\n\n    return {\n      inject: async (token: any, args?: any) => {\n        // Track dependency and check for scope upgrade\n        const actualToken =\n          typeof token === 'function'\n            ? this.tokenResolver.normalizeToken(token)\n            : token\n        const realToken = this.tokenResolver.getRealToken(actualToken)\n        const depRecord = this.registry.get(realToken)\n        const depScope = depRecord.scope\n\n        // Generate dependency name - if dependency is Request-scoped and we have requestId, use it\n        const dependencyRequestId =\n          depScope === InjectableScope.Request ? requestId : undefined\n        const finalDepName = this.nameResolver.generateInstanceName(\n          actualToken,\n          args,\n          dependencyRequestId,\n          depScope,\n        )\n\n        // Check if current service needs scope upgrade\n        // If current service is Singleton and dependency is Request, upgrade current service\n        if (\n          scope === InjectableScope.Singleton &&\n          depScope === InjectableScope.Request &&\n          requestStorage &&\n          requestId\n        ) {\n          // Check and perform scope upgrade for current service\n          // Use the dependency name with requestId for the check\n          const [needsUpgrade, newServiceName] =\n            this.scopeTracker.checkAndUpgradeScope(\n              serviceName,\n              scope,\n              finalDepName,\n              depScope,\n              serviceToken,\n              this.storage,\n              requestStorage,\n              requestId,\n            )\n\n          if (needsUpgrade && newServiceName) {\n            // Service was upgraded - update the service name in context\n            // The holder will be moved to request storage by ScopeTracker\n            // For now, we continue with the current resolution\n            // Future resolutions will use the new name\n          }\n        }\n\n        // Track dependency\n        deps.add(finalDepName)\n\n        // Resolve dependency\n        // Resolution context is automatically used by the injectors system for circular dependency detection\n        return container.get(token, args)\n      },\n      container,\n      addDestroyListener: (listener: () => void) => {\n        destroyListeners.push(listener)\n      },\n      getDestroyListeners: () => destroyListeners,\n      serviceName,\n      dependencies: deps,\n      scope,\n      trackDependency: (name: string, depScope: InjectableScope) => {\n        deps.add(name)\n        // Check for scope upgrade\n        if (\n          scope === InjectableScope.Singleton &&\n          depScope === InjectableScope.Request &&\n          requestStorage &&\n          requestId\n        ) {\n          this.scopeTracker.checkAndUpgradeScope(\n            serviceName,\n            scope,\n            name,\n            depScope,\n            serviceToken,\n            this.storage,\n            requestStorage,\n            requestId,\n          )\n        }\n      },\n    }\n  }\n}\n"],"mappings":"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"}