{"version":3,"file":"scope-tracker.mjs","names":["InjectableScope","Scope","DIError","InstanceStatus","ScopeTracker","registry","nameResolver","logger","checkAndUpgradeScope","currentServiceName","currentServiceScope","dependencyName","dependencyScope","dependencyToken","singletonStorage","requestStorage","requestId","Singleton","Request","warn","log","success","newName","upgradeScopeToRequestSync","error","upgradeScopeToRequest","serviceName","token","undefined","storageError","unknown","upgradeInstanceNameToRequest","updated","updateScope","holderResult","get","holder","message","status","Creating","name","set","delete","updateParentDependencies","oldName","updateDependencyReference"],"sources":["../../../../src/internal/core/scope-tracker.mts"],"sourcesContent":["import type { InjectableScope } from '../../enums/index.mjs'\nimport type { InjectionToken } from '../../token/injection-token.mjs'\nimport type { IHolderStorage } from '../holder/holder-storage.interface.mjs'\n\nimport { InjectableScope as Scope } from '../../enums/index.mjs'\nimport { DIError } from '../../errors/index.mjs'\nimport { InstanceStatus } from '../holder/instance-holder.mjs'\nimport { Registry } from '../../token/registry.mjs'\nimport { NameResolver } from './name-resolver.mjs'\n\n/**\n * Component for tracking and handling scope upgrades.\n *\n * Detects when a Singleton service needs to be upgraded to Request scope\n * and coordinates the scope upgrade process atomically.\n */\nexport class ScopeTracker {\n  constructor(\n    private readonly registry: Registry,\n    private readonly nameResolver: NameResolver,\n    private readonly logger: Console | null = null,\n  ) {}\n\n  /**\n   * Checks if a dependency requires scope upgrade and performs it if needed.\n   * Called during service resolution when a dependency is resolved.\n   *\n   * @param currentServiceName - Name of the service being created\n   * @param currentServiceScope - Current scope of the service being created\n   * @param dependencyName - Name of the dependency being resolved\n   * @param dependencyScope - Scope of the dependency\n   * @param dependencyToken - Token of the dependency\n   * @param singletonStorage - Singleton storage instance\n   * @param requestStorage - Request storage instance (if in request context)\n   * @param requestId - Request ID (if in request context)\n   * @returns [needsUpgrade: boolean, newName?: string] - whether upgrade occurred and new name\n   */\n  checkAndUpgradeScope(\n    currentServiceName: string,\n    currentServiceScope: InjectableScope,\n    dependencyName: string,\n    dependencyScope: InjectableScope,\n    dependencyToken: InjectionToken<any, any>,\n    singletonStorage: IHolderStorage,\n    requestStorage?: IHolderStorage,\n    requestId?: string,\n  ): [boolean, string?] {\n    // Only upgrade if current service is Singleton and dependency is Request\n    if (\n      currentServiceScope !== Scope.Singleton ||\n      dependencyScope !== Scope.Request\n    ) {\n      return [false]\n    }\n\n    // Need request storage and requestId for upgrade\n    if (!requestStorage || !requestId) {\n      this.logger?.warn(\n        `[ScopeTracker] Cannot upgrade scope for ${currentServiceName}: missing requestStorage or requestId`,\n      )\n      return [false]\n    }\n\n    // Perform the upgrade\n    this.logger?.log(\n      `[ScopeTracker] Upgrading ${currentServiceName} from Singleton to Request scope`,\n    )\n\n    try {\n      const [success, newName] = this.upgradeScopeToRequestSync(\n        currentServiceName,\n        dependencyToken,\n        singletonStorage,\n        requestStorage,\n        requestId,\n      )\n\n      if (success && newName) {\n        return [true, newName]\n      }\n    } catch (error) {\n      this.logger?.error(\n        `[ScopeTracker] Error upgrading scope for ${currentServiceName}:`,\n        error,\n      )\n    }\n\n    return [false]\n  }\n\n  /**\n   * Performs the actual scope upgrade from Singleton to Request.\n   * This is the core migration logic.\n   *\n   * @param serviceName - Current service name (without requestId)\n   * @param token - Service injection token\n   * @param singletonStorage - Source storage\n   * @param requestStorage - Target storage\n   * @param requestId - Request ID to include in new name\n   * @returns [success: boolean, newName?: string, error?: DIError]\n   */\n  async upgradeScopeToRequest(\n    serviceName: string,\n    token: InjectionToken<any, any>,\n    singletonStorage: IHolderStorage,\n    requestStorage: IHolderStorage,\n    requestId: string,\n  ): Promise<[boolean, string?, DIError?]> {\n    try {\n      const [success, newName] = this.upgradeScopeToRequestSync(\n        serviceName,\n        token,\n        singletonStorage,\n        requestStorage,\n        requestId,\n      )\n\n      if (success && newName) {\n        return [true, newName]\n      }\n      return [\n        false,\n        undefined,\n        DIError.storageError(\n          'Scope upgrade failed',\n          'upgradeScopeToRequest',\n          serviceName,\n        ),\n      ]\n    } catch (error) {\n      return [\n        false,\n        undefined,\n        error instanceof DIError ? error : DIError.unknown(error as Error),\n      ]\n    }\n  }\n\n  /**\n   * Synchronous part of scope upgrade - handles immediate updates.\n   * Async operations (like waiting for holder creation) should be done separately.\n   */\n  private upgradeScopeToRequestSync(\n    serviceName: string,\n    token: InjectionToken<any, any>,\n    singletonStorage: IHolderStorage,\n    requestStorage: IHolderStorage,\n    requestId: string,\n  ): [boolean, string?] {\n    // 1. Upgrade existing instance name to include requestId\n    // This preserves any args hash that might be in the original name\n    const newName = this.nameResolver.upgradeInstanceNameToRequest(\n      serviceName,\n      requestId,\n    )\n\n    // 2. Update Registry scope to Request (synchronous)\n    const updated = this.registry.updateScope(token, Scope.Request)\n    if (!updated) {\n      this.logger?.warn(\n        `[ScopeTracker] Could not update scope in registry for ${serviceName}`,\n      )\n      return [false]\n    }\n\n    // 3. Check if holder exists in singleton storage\n    const holderResult = singletonStorage.get(serviceName)\n    if (holderResult === null) {\n      // No holder exists yet - just update registry, future resolutions will use request storage\n      return [true, newName]\n    }\n\n    const [error, holder] = holderResult\n    if (error) {\n      this.logger?.warn(\n        `[ScopeTracker] Holder for ${serviceName} is in error state: ${error.message}`,\n      )\n      return [false]\n    }\n\n    if (!holder) {\n      return [false]\n    }\n\n    // 4. If holder is in \"Creating\" state, we need to wait for it before migrating\n    // For now, we'll update the name and move it, but the caller should wait for creation\n    if (holder.status === InstanceStatus.Creating) {\n      // Update holder name\n      holder.name = newName\n      // Move to request storage\n      requestStorage.set(newName, holder)\n      // Remove from singleton storage\n      singletonStorage.delete(serviceName)\n      // Update parent dependencies\n      this.updateParentDependencies(\n        serviceName,\n        newName,\n        singletonStorage,\n        requestStorage,\n      )\n      return [true, newName]\n    }\n\n    // 5. Move holder from singleton to request storage\n    holder.name = newName\n    requestStorage.set(newName, holder)\n    singletonStorage.delete(serviceName)\n\n    // 6. Update all parent dependencies\n    this.updateParentDependencies(\n      serviceName,\n      newName,\n      singletonStorage,\n      requestStorage,\n    )\n\n    return [true, newName]\n  }\n\n  /**\n   * Updates all parent dependencies to reference the new service name.\n   *\n   * @param oldName - Original service name\n   * @param newName - New service name with requestId\n   * @param singletonStorage - Singleton storage to check\n   * @param requestStorage - Request storage to check\n   */\n  updateParentDependencies(\n    oldName: string,\n    newName: string,\n    singletonStorage: IHolderStorage,\n    requestStorage?: IHolderStorage,\n  ): void {\n    // Update dependencies in singleton storage\n    singletonStorage.updateDependencyReference(oldName, newName)\n\n    // Update dependencies in request storage if provided\n    if (requestStorage) {\n      requestStorage.updateDependencyReference(oldName, newName)\n    }\n  }\n}\n"],"mappings":";;;;;;;;;;GAgBA,IAAaI,eAAb,MAAaA;;;;CACX,YACE,UACA,cACA,SAA0C,MAC1C;OAHiBC,WAAAA;OACAC,eAAAA;OACAC,SAAAA;;;;;;;;;;;;;;;IAiBnBC,qBACEC,oBACAC,qBACAC,gBACAC,iBACAC,iBACAC,kBACAC,gBACAC,WACoB;AAEpB,MACEN,wBAAwBT,gBAAMgB,aAC9BL,oBAAoBX,gBAAMiB,QAE1B,QAAO,CAAC,MAAM;AAIhB,MAAI,CAACH,kBAAkB,CAACC,WAAW;AACjC,QAAKT,QAAQY,KACX,2CAA2CV,mBAAmB,uCAAsC;AAEtG,UAAO,CAAC,MAAM;;AAIhB,OAAKF,QAAQa,IACX,4BAA4BX,mBAAmB,kCAAiC;AAGlF,MAAI;GACF,MAAM,CAACY,SAASC,WAAW,KAAKC,0BAC9Bd,oBACAI,iBACAC,kBACAC,gBACAC,UAAAA;AAGF,OAAIK,WAAWC,QACb,QAAO,CAAC,MAAMA,QAAQ;WAEjBE,OAAO;AACd,QAAKjB,QAAQiB,MACX,4CAA4Cf,mBAAmB,IAC/De,MAAAA;;AAIJ,SAAO,CAAC,MAAM;;;;;;;;;;;;IAchB,MAAMC,sBACJC,aACAC,OACAb,kBACAC,gBACAC,WACuC;AACvC,MAAI;GACF,MAAM,CAACK,SAASC,WAAW,KAAKC,0BAC9BG,aACAC,OACAb,kBACAC,gBACAC,UAAAA;AAGF,OAAIK,WAAWC,QACb,QAAO,CAAC,MAAMA,QAAQ;AAExB,UAAO;IACL;IACAM;IACA1B,QAAQ2B,aACN,wBACA,yBACAH,YAAAA;IAEH;WACMF,OAAO;AACd,UAAO;IACL;IACAI;IACAJ,iBAAiBtB,UAAUsB,QAAQtB,QAAQ4B,QAAQN,MAAAA;IACpD;;;;;;IAQL,0BACEE,aACAC,OACAb,kBACAC,gBACAC,WACoB;EAGpB,MAAMM,UAAU,KAAKhB,aAAayB,6BAChCL,aACAV,UAAAA;AAKF,MAAI,CADY,KAAKX,SAAS4B,YAAYN,OAAO1B,gBAAMiB,QAAO,EAChD;AACZ,QAAKX,QAAQY,KACX,yDAAyDO,cAAa;AAExE,UAAO,CAAC,MAAM;;EAIhB,MAAMQ,eAAepB,iBAAiBqB,IAAIT,YAAAA;AAC1C,MAAIQ,iBAAiB,KAEnB,QAAO,CAAC,MAAMZ,QAAQ;EAGxB,MAAM,CAACE,OAAOY,UAAUF;AACxB,MAAIV,OAAO;AACT,QAAKjB,QAAQY,KACX,6BAA6BO,YAAY,sBAAsBF,MAAMa,UAAS;AAEhF,UAAO,CAAC,MAAM;;AAGhB,MAAI,CAACD,OACH,QAAO,CAAC,MAAM;AAKhB,MAAIA,OAAOE,WAAWnC,eAAeoC,UAAU;AAE7CH,UAAOI,OAAOlB;AAEdP,kBAAe0B,IAAInB,SAASc,OAAAA;AAE5BtB,oBAAiB4B,OAAOhB,YAAAA;AAExB,QAAKiB,yBACHjB,aACAJ,SACAR,kBACAC,eAAAA;AAEF,UAAO,CAAC,MAAMO,QAAQ;;AAIxBc,SAAOI,OAAOlB;AACdP,iBAAe0B,IAAInB,SAASc,OAAAA;AAC5BtB,mBAAiB4B,OAAOhB,YAAAA;AAGxB,OAAKiB,yBACHjB,aACAJ,SACAR,kBACAC,eAAAA;AAGF,SAAO,CAAC,MAAMO,QAAQ;;;;;;;;;IAWxBqB,yBACEC,SACAtB,SACAR,kBACAC,gBACM;AAEND,mBAAiB+B,0BAA0BD,SAAStB,QAAAA;AAGpD,MAAIP,eACFA,gBAAe8B,0BAA0BD,SAAStB,QAAAA"}