{"version":3,"file":"abstract-container.mjs","names":["InjectableScope","InjectableType","DIError","DIErrorCode","InstanceStatus","StubFactoryClass","BoundInjectionToken","InjectionToken","AbstractContainer","calculateInstanceName","token","args","tokenResolver","getTokenResolver","err","actualToken","validatedArgs","validateAndResolveTokenArgs","code","FactoryTokenNotResolved","TokenValidationError","realToken","getRealToken","registry","getRegistry","scope","has","get","defaultScope","getNameResolver","generateInstanceName","Request","requestId","undefined","isRegistered","getRegistryToken","ready","getServiceInvalidator","readyWithStorage","getStorage","tryGetSync","tryGetSyncFromStorage","storage","Singleton","instanceName","normalizeToken","result","holder","status","Created","instance","addInstance","addInstanceToStorage","schema","schemaType","def","type","tokenSchemaRequiredError","name","normalizedToken","set","Class","value","storeInstance"],"sources":["../../../src/container/abstract-container.mts"],"sourcesContent":["import type { z, ZodType } from 'zod/v4'\n\nimport type { IContainer } from '../interfaces/container.interface.mjs'\nimport type { Factorable } from '../interfaces/factory.interface.mjs'\nimport type { NameResolver } from '../internal/core/name-resolver.mjs'\nimport type { ServiceInvalidator } from '../internal/core/service-invalidator.mjs'\nimport type { TokenResolver } from '../internal/core/token-resolver.mjs'\nimport type {\n  ClassType,\n  ClassTypeWithArgument,\n  InjectionTokenSchemaType,\n} from '../token/injection-token.mjs'\nimport type { Registry } from '../token/registry.mjs'\nimport type { Join, UnionToArray } from '../utils/types.mjs'\n\nimport { InjectableScope, InjectableType } from '../enums/index.mjs'\nimport { DIError, DIErrorCode } from '../errors/index.mjs'\nimport { InstanceStatus } from '../internal/holder/instance-holder.mjs'\nimport { UnifiedStorage } from '../internal/holder/unified-storage.mjs'\nimport { StubFactoryClass } from '../internal/index.mjs'\nimport {\n  BoundInjectionToken,\n  FactoryInjectionToken,\n  InjectionToken,\n} from '../token/injection-token.mjs'\n\n/**\n * Abstract base class for dependency injection containers.\n *\n * Provides shared implementation for common container operations.\n * Both Container and ScopedContainer extend this class.\n */\nexport abstract class AbstractContainer implements IContainer {\n  /**\n   * The default scope used when adding instances without explicit registration.\n   */\n  protected abstract readonly defaultScope: InjectableScope\n\n  /**\n   * The request ID for scoped containers, undefined for root container.\n   */\n  protected abstract readonly requestId: string | undefined\n\n  // ============================================================================\n  // ABSTRACT METHODS - Must be implemented by subclasses\n  // ============================================================================\n\n  /**\n   * Gets the storage for this container.\n   */\n  abstract getStorage(): UnifiedStorage\n\n  /**\n   * Gets the registry for this container.\n   */\n  protected abstract getRegistry(): Registry\n\n  /**\n   * Gets the token resolver.\n   */\n  protected abstract getTokenResolver(): TokenResolver\n\n  /**\n   * Gets the name resolver.\n   */\n  protected abstract getNameResolver(): NameResolver\n\n  /**\n   * Gets the service invalidator.\n   */\n  protected abstract getServiceInvalidator(): ServiceInvalidator\n\n  /**\n   * Gets an instance from the container.\n   */\n  // #1 Simple class\n  abstract 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  abstract get<T extends ClassTypeWithArgument<R>, R>(\n    token: T,\n    args: R,\n  ): Promise<InstanceType<T>>\n  // #2 Token with required Schema\n  abstract 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  abstract 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  abstract get<T>(token: InjectionToken<T, undefined>): Promise<T>\n  abstract get<T>(token: BoundInjectionToken<T, any>): Promise<T>\n  abstract get<T>(token: FactoryInjectionToken<T, any>): Promise<T>\n\n  /**\n   * Invalidates a service and its dependencies.\n   */\n  abstract invalidate(service: unknown): Promise<void>\n\n  /**\n   * Disposes the container and cleans up all resources.\n   */\n  abstract dispose(): Promise<void>\n\n  // ============================================================================\n  // SHARED IMPLEMENTATIONS\n  // ============================================================================\n\n  /**\n   * Calculates the instance name for a given token and optional arguments.\n   *\n   * @internal\n   * @param token The class type, InjectionToken, BoundInjectionToken, or FactoryInjectionToken\n   * @param args Optional arguments (ignored for BoundInjectionToken which uses its bound value)\n   * @returns The calculated instance name string, or null if the token is a FactoryInjectionToken that is not yet resolved\n   */\n  calculateInstanceName(\n    token:\n      | ClassType\n      | InjectionToken<any, any>\n      | BoundInjectionToken<any, any>\n      | FactoryInjectionToken<any, any>,\n    args?: unknown,\n  ): string | null {\n    const tokenResolver = this.getTokenResolver()\n\n    // Use validateAndResolveTokenArgs to handle token normalization and arg resolution\n    const [err, { actualToken, validatedArgs }] =\n      tokenResolver.validateAndResolveTokenArgs(token, args)\n\n    if (err) {\n      // Return null if factory token is not resolved\n      if (\n        err instanceof DIError &&\n        err.code === DIErrorCode.FactoryTokenNotResolved\n      ) {\n        return null\n      }\n\n      // Return null if validation fails (can't calculate name with invalid args)\n      if (\n        err instanceof DIError &&\n        err.code === DIErrorCode.TokenValidationError\n      ) {\n        return null\n      }\n    }\n\n    // Get the real token for registry lookup to determine scope\n    const realToken = this.getTokenResolver().getRealToken(actualToken)\n\n    const registry = this.getRegistry()\n\n    // Get scope from registry, or use default scope if not registered\n    const scope = registry.has(realToken)\n      ? registry.get(realToken).scope\n      : this.defaultScope\n\n    // Generate instance name using the name resolver with actual token and validated args\n    return this.getNameResolver().generateInstanceName(\n      actualToken,\n      validatedArgs,\n      scope === InjectableScope.Request ? this.requestId : undefined,\n      scope,\n    )\n  }\n\n  /**\n   * Checks if a service is registered in the container.\n   */\n  isRegistered(token: any): boolean {\n    const realToken = this.getTokenResolver().getRegistryToken(token)\n    return this.getRegistry().has(realToken)\n  }\n\n  /**\n   * Waits for all pending operations to complete.\n   */\n  async ready(): Promise<void> {\n    await this.getServiceInvalidator().readyWithStorage(this.getStorage())\n  }\n\n  /**\n   * @internal\n   * Attempts to get an instance synchronously if it already exists.\n   */\n  tryGetSync<T>(token: any, args?: any): T | null {\n    return this.tryGetSyncFromStorage(\n      token,\n      args,\n      this.getStorage(),\n      this.requestId,\n    )\n  }\n\n  /**\n   * @internal\n   * Internal method for getting instances synchronously with configurable storage.\n   */\n  protected tryGetSyncFromStorage<T>(\n    token: any,\n    args: any,\n    storage: UnifiedStorage,\n    requestId?: string,\n  ): T | null {\n    const tokenResolver = this.getTokenResolver()\n    const realToken = tokenResolver.getRegistryToken(token)\n    const registry = this.getRegistry()\n    const scope = registry.has(realToken)\n      ? registry.get(realToken).scope\n      : InjectableScope.Singleton\n\n    try {\n      const instanceName = this.getNameResolver().generateInstanceName(\n        tokenResolver.normalizeToken(token),\n        args,\n        requestId,\n        scope,\n      )\n\n      const result = storage.get(instanceName)\n      if (result && result[0] === undefined && result[1]) {\n        const holder = result[1]\n        if (holder.status === InstanceStatus.Created) {\n          return holder.instance as T\n        }\n      }\n    } catch {\n      // Ignore error\n    }\n\n    return null\n  }\n\n  /**\n   * Adds an instance to the container.\n   * Accepts class types, InjectionTokens, and BoundInjectionTokens.\n   * Rejects InjectionTokens with required schemas (use BoundInjectionToken instead).\n   *\n   * @param token The class type, InjectionToken, or BoundInjectionToken to register the instance for\n   * @param instance The instance to store\n   */\n  addInstance<T>(\n    token: ClassType | InjectionToken<T, any> | BoundInjectionToken<T, any>,\n    instance: T,\n  ): void {\n    this.addInstanceToStorage(\n      token,\n      instance,\n      this.getStorage(),\n      this.defaultScope,\n      this.requestId,\n    )\n  }\n\n  /**\n   * @internal\n   * Internal method for adding instances with configurable scope and storage.\n   */\n  protected addInstanceToStorage<T>(\n    token: ClassType | InjectionToken<T, any> | BoundInjectionToken<T, any>,\n    instance: T,\n    storage: UnifiedStorage,\n    scope: InjectableScope,\n    requestId?: string,\n  ): void {\n    // Check if token is an InjectionToken with required schema\n    // BoundInjectionToken is allowed (it already has a value bound)\n    if (token instanceof InjectionToken) {\n      // Check if schema exists and is required (not optional)\n      if (token.schema) {\n        const schemaType = (token.schema as ZodType)?.def?.type\n        if (schemaType !== 'optional') {\n          throw DIError.tokenSchemaRequiredError(token.name)\n        }\n      }\n    }\n\n    const tokenResolver = this.getTokenResolver()\n    const registry = this.getRegistry()\n\n    // Normalize the token\n    const normalizedToken = tokenResolver.normalizeToken(token)\n    const realToken = tokenResolver.getRegistryToken(token)\n\n    // If it's a class type and not registered, register it with the given scope\n    if (typeof token === 'function' && !registry.has(realToken)) {\n      registry.set(realToken, scope, token, InjectableType.Class)\n    } else if (!registry.has(realToken)) {\n      // Set a stub factory class to avoid errors when getting instances of unregistered factory tokens\n      registry.set(\n        realToken,\n        scope,\n        StubFactoryClass,\n        InjectableType.Class,\n        // Lowest priority to avoid conflicts with other registered tokens\n        -1,\n      )\n    }\n\n    // Generate instance name with the given scope\n    const instanceName = this.getNameResolver().generateInstanceName(\n      normalizedToken,\n      normalizedToken instanceof BoundInjectionToken\n        ? normalizedToken.value\n        : undefined,\n      requestId,\n      scope,\n    )\n\n    // Store the instance\n    storage.storeInstance(instanceName, instance)\n  }\n}\n"],"mappings":"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"}