{"version":3,"file":"unified-storage.mjs","names":["InjectableScope","InjectableType","DIError","InstanceStatus","UnifiedStorage","scope","holders","Map","dependents","Singleton","get","instanceName","holder","status","Destroying","instanceDestroying","Error","instance","Creating","Created","undefined","set","deps","size","registerDependencies","delete","removeFromDependentsIndex","createHolder","type","deferred","Promise","withResolvers","name","creationPromise","promise","destroyPromise","destroyListeners","createdAt","Date","now","waitingFor","Set","storeInstance","storageError","Class","onServiceDestroy","handles","getAllNames","Array","from","keys","forEach","callback","findByInstance","values","findDependents","updateDependencyReference","oldName","newName","has","add","oldDependents","newDependents","dependent","depName","entries","holderName","dep"],"sources":["../../../../src/internal/holder/unified-storage.mts"],"sourcesContent":["import type { OnServiceDestroy } from '../../interfaces/index.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 * Unified storage implementation that works the same way regardless of scope.\n * Replaces RequestContext, HolderManager, SingletonStorage, RequestStorage.\n *\n * Scope is just metadata - storage operations are identical for all scopes.\n * Different storage instances are just isolated storage spaces.\n */\nexport class UnifiedStorage implements IHolderStorage {\n  readonly scope: InjectableScope\n\n  private readonly holders = new Map<string, InstanceHolder>()\n  /**\n   * Reverse dependency index: maps a dependency name to the set of holder names that depend on it.\n   * This allows O(1) lookup of dependents instead of O(n) iteration.\n   */\n  private readonly dependents = new Map<string, Set<string>>()\n\n  constructor(scope: InjectableScope = InjectableScope.Singleton) {\n    this.scope = scope\n  }\n\n  get<T = unknown>(instanceName: string): HolderGetResult<T> {\n    const holder = this.holders.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.holders.set(instanceName, holder)\n    // Register dependencies in reverse index\n    if (holder.deps.size > 0) {\n      this.registerDependencies(instanceName, holder.deps)\n    }\n  }\n\n  delete(instanceName: string): boolean {\n    const holder = this.holders.get(instanceName)\n    if (holder) {\n      // Remove this holder from the reverse index for all its dependencies\n      this.removeFromDependentsIndex(instanceName, holder.deps)\n    }\n    return this.holders.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    const deferred = Promise.withResolvers<[undefined, T]>()\n\n    const holder: InstanceHolder<T> = {\n      status: InstanceStatus.Creating,\n      name: instanceName,\n      instance: null,\n      creationPromise: deferred.promise,\n      destroyPromise: null,\n      type,\n      scope: this.scope,\n      deps,\n      destroyListeners: [],\n      createdAt: Date.now(),\n      waitingFor: new Set(),\n    }\n\n    return [deferred, holder]\n  }\n\n  storeInstance(instanceName: string, instance: unknown): void {\n    const holder = this.holders.get(instanceName)\n    if (holder) {\n      throw DIError.storageError(\n        'Instance already stored',\n        'storeInstance',\n        instanceName,\n      )\n    }\n    this.set(instanceName, {\n      status: InstanceStatus.Created,\n      name: instanceName,\n      instance,\n      creationPromise: null,\n      destroyPromise: null,\n      type: InjectableType.Class,\n      scope: this.scope,\n      deps: new Set(),\n      destroyListeners:\n        typeof instance === 'object' &&\n        instance !== null &&\n        'onServiceDestroy' in instance\n          ? [(instance as OnServiceDestroy).onServiceDestroy]\n          : [],\n      createdAt: Date.now(),\n      waitingFor: new Set(),\n    })\n  }\n\n  handles(scope: InjectableScope): boolean {\n    return scope === this.scope\n  }\n\n  // ============================================================================\n  // ITERATION AND QUERY\n  // ============================================================================\n\n  getAllNames(): string[] {\n    return Array.from(this.holders.keys())\n  }\n\n  forEach(callback: (name: string, holder: InstanceHolder) => void): void {\n    for (const [name, holder] of this.holders) {\n      callback(name, holder)\n    }\n  }\n\n  findByInstance(instance: unknown): InstanceHolder | null {\n    for (const holder of this.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 = this.dependents.get(instanceName)\n    return dependents ? Array.from(dependents) : []\n  }\n\n  /**\n   * Updates dependency references when instance names change.\n   * Used during scope upgrades when instance names are regenerated with requestId.\n   *\n   * @param oldName The old instance name\n   * @param newName The new instance name\n   */\n  updateDependencyReference(oldName: string, newName: string): void {\n    // Update all holders that reference oldName in their deps Set\n    for (const holder of this.holders.values()) {\n      if (holder.deps.has(oldName)) {\n        holder.deps.delete(oldName)\n        holder.deps.add(newName)\n      }\n    }\n\n    // Update reverse dependency index\n    const oldDependents = this.dependents.get(oldName)\n    if (oldDependents) {\n      // Move dependents from old name to new name\n      const newDependents = this.dependents.get(newName) || new Set<string>()\n      for (const dependent of oldDependents) {\n        newDependents.add(dependent)\n      }\n      this.dependents.set(newName, newDependents)\n      this.dependents.delete(oldName)\n    }\n\n    // Update reverse index entries - if oldName was a dependency, update all holders that depend on it\n    for (const [depName, dependents] of this.dependents.entries()) {\n      if (depName === oldName) {\n        // This shouldn't happen, but handle it just in case\n        const newDependents = this.dependents.get(newName) || new Set<string>()\n        for (const dependent of dependents) {\n          newDependents.add(dependent)\n        }\n        this.dependents.set(newName, newDependents)\n        this.dependents.delete(oldName)\n      }\n    }\n  }\n\n  // ============================================================================\n  // INTERNAL HELPERS\n  // ============================================================================\n\n  /**\n   * Registers a holder's dependencies in the reverse index.\n   */\n  private registerDependencies(holderName: string, deps: Set<string>): void {\n    for (const dep of deps) {\n      let dependents = this.dependents.get(dep)\n      if (!dependents) {\n        dependents = new Set()\n        this.dependents.set(dep, dependents)\n      }\n      dependents.add(holderName)\n    }\n  }\n\n  /**\n   * Removes a holder from the reverse dependency index.\n   */\n  private removeFromDependentsIndex(\n    holderName: string,\n    deps: Set<string>,\n  ): void {\n    for (const dep of deps) {\n      const dependents = this.dependents.get(dep)\n      if (dependents) {\n        dependents.delete(holderName)\n        if (dependents.size === 0) {\n          this.dependents.delete(dep)\n        }\n      }\n    }\n  }\n}\n"],"mappings":"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"}