//#region src/dependencyLookUp.d.ts
interface SkipSelfDecorator {
  (): any;
  new (): SkipSelfDecorator;
}
/**
 * A parameter decorator that instructs the injector to skip the current
 * injector when resolving this dependency, and start the lookup from
 * the parent injector.
 *
 * This is useful when you want to get a dependency from a parent injector
 * even if the current injector has the same dependency registered.
 *
 * @example
 * ```typescript
 * class ChildService {
 *   constructor(
 *     @SkipSelf() @Inject(IConfig) private parentConfig: IConfig
 *   ) {}
 * }
 * ```
 */
declare const SkipSelf: SkipSelfDecorator;
interface SelfDecorator {
  (): any;
  new (): SelfDecorator;
}
/**
 * A parameter decorator that instructs the injector to only look for
 * this dependency in the current injector, without searching parent injectors.
 *
 * If the dependency is not found in the current injector, an error will be thrown
 * (or `null` will be returned if used with `@Optional()`).
 *
 * @example
 * ```typescript
 * class MyService {
 *   constructor(
 *     @Self() @Inject(ILocalConfig) private localConfig: ILocalConfig
 *   ) {}
 * }
 *
 * // With optional - returns null if not found locally
 * class MyService {
 *   constructor(
 *     @Self() @Optional(ILocalCache) private cache: ILocalCache | null
 *   ) {}
 * }
 * ```
 */
declare const Self: SelfDecorator;
//#endregion
//#region src/error.d.ts
/**
 * Base error class for all errors thrown by redi.
 *
 * All error messages are prefixed with `[redi]:` for easy identification.
 *
 * @example
 * ```typescript
 * try {
 *   injector.get(UnregisteredService);
 * } catch (error) {
 *   if (error instanceof RediError) {
 *     console.error('Redi error:', error.message);
 *   }
 * }
 * ```
 */
declare class RediError extends Error {
  constructor(message: string);
}
//#endregion
//#region src/types.d.ts
/**
 * Specifies how many instances of a dependency should be retrieved.
 *
 * - `REQUIRED`: Exactly one instance must exist (default behavior)
 * - `OPTIONAL`: Zero or one instance, returns `null` if not found
 * - `MANY`: All registered instances as an array
 */
declare enum Quantity {
  /** Retrieve all registered instances as an array. */
  MANY = "many",
  /** Retrieve zero or one instance. Returns `null` if not registered. */
  OPTIONAL = "optional",
  /** Exactly one instance must be registered (default). Throws if not found. */
  REQUIRED = "required",
}
/**
 * Specifies which injectors should be searched when resolving a dependency.
 *
 * - `SELF`: Only search the current injector
 * - `SKIP_SELF`: Skip the current injector, start from parent
 */
declare enum LookUp {
  /** Only search in the current injector, do not look in parent injectors. */
  SELF = "self",
  /** Skip the current injector and start searching from the parent injector. */
  SKIP_SELF = "skipSelf",
}
//#endregion
//#region src/dependencyQuantity.d.ts
interface ManyDecorator {
  (id?: DependencyIdentifier<any>): any;
  new (): ManyDecorator;
}
/**
 * A parameter decorator that indicates the dependency should be resolved
 * as an array containing all registered instances of the dependency.
 *
 * Use this when multiple implementations are registered for the same identifier
 * and you want to receive all of them.
 *
 * @param id - Optional dependency identifier. If not provided, must be used
 *   after `@Inject()` decorator.
 *
 * @example
 * ```typescript
 * // Register multiple handlers
 * const injector = new Injector([
 *   [IHandler, { useClass: LoggingHandler }],
 *   [IHandler, { useClass: ValidationHandler }],
 *   [IHandler, { useClass: AuthHandler }],
 * ]);
 *
 * class EventProcessor {
 *   constructor(@Many(IHandler) private handlers: IHandler[]) {
 *     // handlers contains all three registered handlers
 *   }
 * }
 * ```
 */
declare const Many: ManyDecorator;
interface OptionalDecorator {
  (id?: DependencyIdentifier<any>): any;
  new (): OptionalDecorator;
}
/**
 * A parameter decorator that marks a dependency as optional.
 *
 * If the dependency is not registered, `null` will be injected instead
 * of throwing an error.
 *
 * @param id - Optional dependency identifier. If not provided, must be used
 *   after `@Inject()` decorator.
 *
 * @example
 * ```typescript
 * class MyService {
 *   constructor(
 *     @Optional(ICacheService) private cache: ICacheService | null
 *   ) {
 *     // cache will be null if ICacheService is not registered
 *   }
 * }
 *
 * // Or with @Inject
 * class MyService {
 *   constructor(
 *     @Optional() @Inject(ICacheService) private cache: ICacheService | null
 *   ) {}
 * }
 * ```
 */
declare const Optional: OptionalDecorator;
interface InjectDecorator {
  (id: DependencyIdentifier<any>): any;
  new (): InjectDecorator;
}
/**
 * A parameter decorator that declares a required dependency to be injected.
 *
 * This is the primary way to declare dependencies when using decorators.
 * The dependency must be registered in the injector or its parent injectors,
 * otherwise an error will be thrown.
 *
 * @param id - The dependency identifier (class, string, or identifier created by `createIdentifier`).
 *
 * @example
 * ```typescript
 * class UserService {
 *   constructor(
 *     @Inject(AuthService) private auth: AuthService,
 *     @Inject(ILogger) private logger: ILogger
 *   ) {}
 * }
 *
 * // The dependency will be injected automatically
 * const injector = new Injector([[AuthService], [ILogger, { useClass: ConsoleLogger }]]);
 * const userService = injector.get(UserService);
 * ```
 */
declare const Inject: InjectDecorator;
//#endregion
//#region src/dependencyWithNew.d.ts
interface ToSelfDecorator {
  (): any;
  new (): ToSelfDecorator;
}
/**
 * A parameter decorator that instructs the injector to always create
 * a new instance of the dependency instead of returning the cached singleton.
 *
 * By default, dependencies are singletons within an injector. Using `@WithNew()`
 * will create a fresh instance each time it's injected.
 *
 * @example
 * ```typescript
 * class RequestHandler {
 *   constructor(
 *     // Each RequestHandler gets its own RequestContext
 *     @WithNew() @Inject(RequestContext) private context: RequestContext
 *   ) {}
 * }
 *
 * // Without @WithNew, all RequestHandlers would share the same context
 * ```
 */
declare const WithNew: ToSelfDecorator;
//#endregion
//#region src/dependencyItem.d.ts
/**
 * Represents a class constructor type.
 *
 * @template T - The type of instance the constructor creates.
 */
interface Ctor<T> {
  new (...args: any[]): T;
  name: string;
}
/**
 * Type guard to check if a value is a constructor function.
 *
 * @param thing - The value to check.
 * @returns `true` if the value is a function (constructor), `false` otherwise.
 */
declare function isCtor<T>(thing: unknown): thing is Ctor<T>;
/**
 * Hooks that can be attached to dependency items for lifecycle events.
 *
 * @template T - The type of the dependency instance.
 */
interface DependencyItemHooks<T> {
  /** Called after the dependency instance is created. */
  onInstantiation?: (instance: T) => void;
}
/**
 * A dependency item that provides a class constructor.
 *
 * When resolved, an instance of the class will be created with its dependencies injected.
 *
 * @template T - The type of the class instance.
 *
 * @example
 * ```typescript
 * const injector = new Injector([
 *   [ILogger, { useClass: ConsoleLogger }],
 *   [ICache, { useClass: RedisCache, lazy: true }], // Lazy instantiation
 * ]);
 * ```
 */
interface ClassDependencyItem<T> extends DependencyItemHooks<T> {
  /** The class constructor to instantiate. */
  useClass: Ctor<T>;
  /** If `true`, the instance will be created lazily when first accessed. */
  lazy?: boolean;
}
/**
 * Type guard to check if a value is a ClassDependencyItem.
 *
 * @param thing - The value to check.
 * @returns `true` if the value has a `useClass` property.
 */
declare function isClassDependencyItem<T>(thing: unknown): thing is ClassDependencyItem<T>;
/**
 * Modifier decorators that can be applied to factory dependencies.
 */
type FactoryDepModifier = typeof Self | typeof SkipSelf | typeof Optional | typeof Many | typeof WithNew;
/**
 * A factory dependency declaration.
 *
 * Can be either a simple dependency identifier or an array with modifiers.
 *
 * @template T - The type of the dependency.
 *
 * @example
 * ```typescript
 * // Simple dependency
 * const dep1: FactoryDep<AuthService> = AuthService;
 *
 * // With modifiers
 * const dep2: FactoryDep<CacheService> = [Optional, CacheService];
 * ```
 */
type FactoryDep<T> = [...FactoryDepModifier[], DependencyIdentifier<T>] | DependencyIdentifier<T>;
/**
 * A dependency item that uses a factory function to create instances.
 *
 * The factory function receives resolved dependencies as arguments
 * and returns the dependency instance.
 *
 * @template T - The type of the instance the factory creates.
 *
 * @example
 * ```typescript
 * const injector = new Injector([
 *   [IConfig, {
 *     useFactory: (env: EnvService) => ({
 *       apiUrl: env.get('API_URL'),
 *       timeout: 5000,
 *     }),
 *     deps: [EnvService],
 *   }],
 * ]);
 * ```
 */
interface FactoryDependencyItem<T> extends DependencyItemHooks<T> {
  /** The factory function that creates the dependency instance. */
  useFactory: (...deps: any[]) => T;
  /** If `true`, the factory will be called each time the dependency is requested. */
  dynamic?: true;
  /** Dependencies to inject into the factory function as arguments. */
  deps?: FactoryDep<any>[];
}
/**
 * Type guard to check if a value is a FactoryDependencyItem.
 *
 * @param thing - The value to check.
 * @returns `true` if the value has a `useFactory` property.
 */
declare function isFactoryDependencyItem<T>(thing: unknown): thing is FactoryDependencyItem<T>;
/**
 * A dependency item that provides a pre-existing value.
 *
 * Use this when you have a value that doesn't need to be constructed.
 *
 * @template T - The type of the value.
 *
 * @example
 * ```typescript
 * const injector = new Injector([
 *   ['API_URL', { useValue: 'https://api.example.com' }],
 *   [IConfig, { useValue: { timeout: 5000, retries: 3 } }],
 * ]);
 * ```
 */
interface ValueDependencyItem<T> extends DependencyItemHooks<T> {
  /** The value to use as the dependency. */
  useValue: T;
}
/**
 * Type guard to check if a value is a ValueDependencyItem.
 *
 * @param thing - The value to check.
 * @returns `true` if the value has a `useValue` property.
 */
declare function isValueDependencyItem<T>(thing: unknown): thing is ValueDependencyItem<T>;
/**
 * Reuse an existing dependency. You can consider it as an alias to another dependency.
 */
interface ExistingDependencyItem<T> extends DependencyItemHooks<T> {
  /**
   * The identifier of the existing dependency.
   */
  useExisting: DependencyIdentifier<T>;
}
/**
 * A dependency item that is resolved asynchronously.
 *
 * Use this for dependencies that require async initialization,
 * such as dynamic imports or async configuration loading.
 *
 * @template T - The type of the dependency.
 *
 * @example
 * ```typescript
 * const injector = new Injector([
 *   [IHeavyModule, {
 *     useAsync: () => import('./heavy-module').then(m => m.HeavyModule),
 *   }],
 * ]);
 *
 * // Must use getAsync to retrieve
 * const module = await injector.getAsync(IHeavyModule);
 * ```
 */
interface AsyncDependencyItem<T> extends DependencyItemHooks<T> {
  /**
   * A function that returns a Promise resolving to:
   * - The dependency instance directly
   * - A class constructor to instantiate
   * - A tuple of [identifier, dependency item] for further resolution
   */
  useAsync: () => Promise<T | Ctor<T> | [DependencyIdentifier<T>, SyncDependencyItem<T>]>;
}
/**
 * Type guard to check if a value is an AsyncDependencyItem.
 *
 * @param thing - The value to check.
 * @returns `true` if the value has a `useAsync` property.
 */
declare function isAsyncDependencyItem<T>(thing: unknown): thing is AsyncDependencyItem<T>;
declare const AsyncHookSymbol: unique symbol;
/**
 * A hook returned when getting an async dependency synchronously.
 *
 * When you call `injector.get()` on an async dependency, you receive an
 * AsyncHook instead of the actual instance. Call `whenReady()` to get
 * a Promise that resolves to the actual dependency.
 *
 * @template T - The type of the dependency.
 *
 * @example
 * ```typescript
 * const hook = injector.get(IAsyncService);
 * if (isAsyncHook(hook)) {
 *   const service = await hook.whenReady();
 * }
 *
 * // Or use getAsync directly
 * const service = await injector.getAsync(IAsyncService);
 * ```
 */
interface AsyncHook<T> {
  __symbol: typeof AsyncHookSymbol;
  /** Returns a Promise that resolves when the async dependency is ready. */
  whenReady: () => Promise<T>;
}
/**
 * Type guard to check if a value is an AsyncHook.
 *
 * @param thing - The value to check.
 * @returns `true` if the value is an AsyncHook.
 */
declare function isAsyncHook<T>(thing: unknown): thing is AsyncHook<T>;
/**
 * A synchronous dependency item. Can be one of:
 * - `ClassDependencyItem` - Provides a class to instantiate
 * - `FactoryDependencyItem` - Provides a factory function
 * - `ExistingDependencyItem` - Aliases another dependency
 * - `ValueDependencyItem` - Provides a static value
 *
 * @template T - The type of the dependency.
 */
type SyncDependencyItem<T> = ClassDependencyItem<T> | FactoryDependencyItem<T> | ExistingDependencyItem<T> | ValueDependencyItem<T>;
/**
 * Any dependency item, either synchronous or asynchronous.
 *
 * @template T - The type of the dependency.
 */
type DependencyItem<T> = SyncDependencyItem<T> | AsyncDependencyItem<T>;
//#endregion
//#region src/dependencyForwardRef.d.ts
/**
 * A wrapper that holds a reference to a class constructor that may not be defined yet.
 * Used to resolve circular dependencies between TypeScript files.
 *
 * @template T - The type of the class instance.
 */
interface ForwardRef<T> {
  /** Unwraps and returns the actual class constructor. */
  unwrap: () => Ctor<T>;
}
/**
 * Create a forward reference to a class that may not be defined yet.
 *
 * This is useful when you have circular dependencies between files.
 * Instead of directly referencing a class (which may be undefined due to
 * the order of ES module initialization), you wrap it in a function that
 * will be called later when the class is definitely available.
 *
 * @param wrapper - A function that returns the class constructor.
 * @returns A ForwardRef object that can be used as a dependency identifier.
 *
 * @example
 * ```typescript
 * // fileA.ts
 * import { forwardRef } from '@wendellhu/redi';
 * import type { ServiceB } from './fileB';
 *
 * class ServiceA {
 *   constructor(@Inject(forwardRef(() => ServiceB)) private b: ServiceB) {}
 * }
 *
 * // fileB.ts
 * import { ServiceA } from './fileA';
 *
 * class ServiceB {
 *   constructor(@Inject(ServiceA) private a: ServiceA) {}
 * }
 * ```
 */
declare function forwardRef<T>(wrapper: () => Ctor<T>): ForwardRef<T>;
//#endregion
//#region src/dependencyIdentifier.d.ts
declare const IdentifierDecoratorSymbol: unique symbol;
/**
 * An identifier decorator created by `createIdentifier`.
 *
 * This type represents a dependency identifier that can also be used as a
 * parameter decorator. It's typically used for interface-based dependency injection.
 *
 * @template T - The type of the dependency.
 *
 * @example
 * ```typescript
 * interface ILogger {
 *   log(message: string): void;
 * }
 *
 * // ILogger is of type IdentifierDecorator<ILogger>
 * const ILogger = createIdentifier<ILogger>('ILogger');
 *
 * class MyService {
 *   // Used as a decorator
 *   constructor(@ILogger private logger: ILogger) {}
 * }
 * ```
 */
interface IdentifierDecorator<T> {
  [IdentifierDecoratorSymbol]: true;
  /** Call signature allowing use as a parameter decorator. */
  (...args: any[]): void;
  /** The name of this identifier, set when calling `createIdentifier`. */
  decoratorName: string;
  /** Returns the decorator name for debugging purposes. */
  toString: () => string;
  /** Phantom type property to preserve the type information. */
  type: T;
}
/**
 * A type that represents all possible forms of dependency identifiers in redi.
 *
 * A dependency identifier can be:
 * - A **string**: Simple string token for value injection
 * - A **class constructor** (`Ctor<T>`): The class itself serves as its own identifier
 * - A **ForwardRef**: A wrapper for handling circular dependencies
 * - An **IdentifierDecorator**: Created by `createIdentifier` for interface-based injection
 *
 * @template T - The type of the dependency.
 *
 * @example
 * ```typescript
 * // Class as identifier
 * class MyService {}
 * injector.get(MyService);
 *
 * // String as identifier
 * injector.add(['API_URL', { useValue: 'https://api.example.com' }]);
 *
 * // IdentifierDecorator for interfaces
 * const ILogger = createIdentifier<ILogger>('ILogger');
 * injector.get(ILogger);
 * ```
 */
type DependencyIdentifier<T> = string | Ctor<T> | ForwardRef<T> | IdentifierDecorator<T>;
//#endregion
//#region src/decorators.d.ts
/**
 * Create a dependency identifier for interface-based injection.
 *
 * Since TypeScript interfaces are erased at runtime, you cannot use them directly
 * as injection tokens. This function creates a unique identifier that can be used
 * to register and retrieve dependencies that implement an interface.
 *
 * The returned identifier can also be used as a decorator.
 *
 * @param id - A unique string name for the identifier. Should be unique across your application.
 * @returns An identifier that can be used both as a dependency token and as a parameter decorator.
 *
 * @example
 * ```typescript
 * interface ILogger {
 *   log(message: string): void;
 * }
 *
 * const ILogger = createIdentifier<ILogger>('ILogger');
 *
 * class ConsoleLogger implements ILogger {
 *   log(message: string) { console.log(message); }
 * }
 *
 * // Use as decorator
 * class MyService {
 *   constructor(@ILogger private logger: ILogger) {}
 * }
 *
 * // Register in injector
 * const injector = new Injector([[ILogger, { useClass: ConsoleLogger }]]);
 * ```
 */
declare function createIdentifier<T>(id: string): IdentifierDecorator<T>;
/**
 * @internal
 */
//#endregion
//#region src/dispose.d.ts
/**
 * An interface for objects that hold resources which should be released
 * when they are no longer needed.
 *
 * When an injector is disposed, it will call `dispose()` on all
 * instantiated dependencies that implement this interface.
 *
 * @example
 * ```typescript
 * class DatabaseConnection implements IDisposable {
 *   private connection: Connection;
 *
 *   async connect() {
 *     this.connection = await createConnection();
 *   }
 *
 *   dispose() {
 *     this.connection?.close();
 *   }
 * }
 *
 * const injector = new Injector([[DatabaseConnection]]);
 * const db = injector.get(DatabaseConnection);
 *
 * // When done, dispose the injector to clean up resources
 * injector.dispose(); // Calls db.dispose() automatically
 * ```
 */
interface IDisposable {
  /** Release any resources held by this object. */
  dispose: () => void;
}
/**
 * Type guard to check if a value implements the IDisposable interface.
 *
 * @param thing - The value to check.
 * @returns `true` if the value has a `dispose` method.
 */
declare function isDisposable(thing: unknown): thing is IDisposable;
//#endregion
//#region src/dependencyCollection.d.ts
/**
 * A tuple representing a dependency registration with an identifier and configuration.
 *
 * @template T - The type of the dependency.
 *
 * @example
 * ```typescript
 * const pair: DependencyPair<ILogger> = [ILogger, { useClass: ConsoleLogger }];
 * ```
 */
type DependencyPair<T> = [DependencyIdentifier<T>, DependencyItem<T>];
/**
 * A tuple representing a class registered as its own identifier.
 *
 * @template T - The type of the class instance.
 */
type DependencyClass<T> = [Ctor<T>];
/**
 * A dependency registration that can be passed to an Injector.
 *
 * Can be either:
 * - `[ClassName]` - A class registered as its own identifier
 * - `[Identifier, DependencyItem]` - An identifier with its configuration
 *
 * @template T - The type of the dependency.
 *
 * @example
 * ```typescript
 * const injector = new Injector([
 *   [MyService],                                    // DependencyClass
 *   [ILogger, { useClass: ConsoleLogger }],        // DependencyPair
 *   ['API_URL', { useValue: 'https://...' }],      // DependencyPair with string
 * ]);
 * ```
 */
type Dependency<T = any> = DependencyPair<T> | DependencyClass<T>;
type DependencyWithInstance<T = any> = [Ctor<T> | DependencyIdentifier<T>, T];
type DependencyOrInstance<T = any> = Dependency<T> | DependencyWithInstance<T>;
//#endregion
//#region src/dependencyDeclare.d.ts
/**
 * Register dependencies on a class without using decorators.
 *
 * This is useful when you cannot use decorators (e.g., in plain JavaScript)
 * or when you need to define dependencies programmatically.
 *
 * @param registerTarget - The target class constructor to register dependencies on.
 * @param deps - An array of dependencies. Each dependency can be:
 *   - A simple identifier (class, string, or identifier created by `createIdentifier`)
 *   - An array with modifiers like `[Optional, SomeService]` or `[Many, SomeService]`
 * @param startIndex - The starting parameter index for dependencies. Default is 0.
 *   Use this when your constructor has custom parameters before the injected dependencies.
 *
 * @example
 * ```typescript
 * class MyService {
 *   constructor(customParam, authService, loggerService) {}
 * }
 *
 * // Register dependencies starting at index 1 (after customParam)
 * setDependencies(MyService, [AuthService, LoggerService], 1);
 *
 * // With optional dependency
 * setDependencies(MyService, [[Optional, CacheService], LoggerService], 1);
 * ```
 */
declare function setDependencies<U>(registerTarget: Ctor<U>, deps: FactoryDep<any>[], startIndex?: number): void;
//#endregion
//#region src/injector.d.ts
/**
 * An accessor object that provides limited access to the injector.
 *
 * This interface is passed to the callback in `injector.invoke()`, providing
 * a safe way to access dependencies without exposing the full injector API.
 *
 * @example
 * ```typescript
 * injector.invoke((accessor) => {
 *   const logger = accessor.get(ILogger);
 *   const hasCache = accessor.has(ICacheService);
 * });
 * ```
 */
interface IAccessor {
  /** Get a dependency by its identifier. */
  get: Injector['get'];
  /** Check if a dependency is available. */
  has: Injector['has'];
}
/**
 * The dependency injection container that manages dependency registration and resolution.
 *
 * The Injector is the core of redi's dependency injection system. It stores
 * dependency registrations and creates instances when requested.
 *
 * Features:
 * - **Hierarchical injection**: Child injectors can inherit from parent injectors
 * - **Lazy instantiation**: Dependencies are created only when first requested
 * - **Singleton by default**: Each dependency is instantiated once per injector
 * - **Lifecycle management**: Automatically disposes dependencies implementing IDisposable
 *
 * @example
 * ```typescript
 * // Basic usage
 * const injector = new Injector([
 *   [AuthService],
 *   [ILogger, { useClass: ConsoleLogger }],
 *   ['API_URL', { useValue: 'https://api.example.com' }],
 * ]);
 *
 * const auth = injector.get(AuthService);
 * const logger = injector.get(ILogger);
 *
 * // Hierarchical injectors
 * const childInjector = injector.createChild([
 *   [ILogger, { useClass: FileLogger }], // Override parent's logger
 * ]);
 *
 * // Clean up when done
 * injector.dispose();
 * ```
 */
declare class Injector {
  private readonly parent;
  private readonly dependencyCollection;
  private readonly resolvedDependencyCollection;
  private readonly children;
  private resolutionOngoing;
  private disposingCallbacks;
  private disposed;
  /**
   * Create a new `Injector` instance.
   *
   * @param dependencies - An array of dependencies to register with this injector.
   *   Each dependency can be:
   *   - `[ClassName]` - Register a class as its own identifier
   *   - `[Identifier, DependencyItem]` - Register with a specific identifier and configuration
   * @param parent - Optional parent injector for hierarchical injection.
   *   Child injectors inherit dependencies from their parent.
   *
   * @example
   * ```typescript
   * // Root injector
   * const rootInjector = new Injector([
   *   [AuthService],
   *   [ILogger, { useClass: ConsoleLogger }],
   * ]);
   *
   * // Child injector with parent
   * const childInjector = new Injector(
   *   [[ICache, { useClass: MemoryCache }]],
   *   rootInjector
   * );
   * ```
   */
  constructor(dependencies?: Dependency[], parent?: Injector | null);
  /**
   * Register a callback to be called when this injector is disposed.
   *
   * Use this to perform cleanup tasks or release external resources
   * when the injector lifecycle ends.
   *
   * **Note:** When your callback is invoked, the injector is already disposed
   * and you cannot interact with it anymore.
   *
   * @param callback - The function to call when the injector is disposed.
   * @returns A disposable that removes the callback when disposed.
   *
   * @example
   * ```typescript
   * const cleanup = injector.onDispose(() => {
   *   console.log('Injector disposed, cleaning up...');
   * });
   *
   * // Later, remove the callback if no longer needed
   * cleanup.dispose();
   * ```
   */
  onDispose(callback: () => void): IDisposable;
  /**
   * Create a child injector that inherits from this injector.
   *
   * The child injector can:
   * - Access all dependencies registered in parent injectors
   * - Override parent dependencies with its own registrations
   * - Have its own scoped dependencies
   *
   * When the parent injector is disposed, all child injectors are disposed first.
   *
   * @param dependencies - Dependencies to register with the child injector.
   * @returns The newly created child injector.
   *
   * @example
   * ```typescript
   * const rootInjector = new Injector([[ILogger, { useClass: ConsoleLogger }]]);
   *
   * const requestInjector = rootInjector.createChild([
   *   [RequestContext, { useClass: RequestContext }],
   * ]);
   *
   * // requestInjector can access both RequestContext and ILogger
   * ```
   */
  createChild(dependencies?: Dependency[]): Injector;
  /**
   * Dispose the injector and release all resources.
   *
   * This method:
   * 1. Recursively disposes all child injectors first
   * 2. Calls `dispose()` on all instantiated dependencies that implement `IDisposable`
   * 3. Clears all internal collections
   * 4. Detaches from parent injector
   * 5. Invokes all registered `onDispose` callbacks
   *
   * After disposal, the injector cannot be used anymore.
   *
   * @example
   * ```typescript
   * const injector = new Injector([[DatabaseService]]);
   * const db = injector.get(DatabaseService);
   *
   * // When done with the injector
   * injector.dispose(); // DatabaseService.dispose() is called automatically
   * ```
   */
  dispose(): void;
  private deleteSelfFromParent;
  /**
   * Add a dependency or pre-created instance to the injector at runtime.
   *
   * This allows dynamic registration of dependencies after the injector is created.
   * Throws an error if the dependency has already been instantiated.
   *
   * @param dependency - A tuple containing:
   *   - `[Ctor]` - A class to register as its own identifier
   *   - `[Identifier, DependencyItem]` - An identifier with its configuration
   *   - `[Identifier, Instance]` - An identifier with a pre-created instance
   *
   * @throws {AddDependencyAfterResolutionError} If the dependency is already resolved.
   *
   * @example
   * ```typescript
   * const injector = new Injector();
   *
   * // Add a class
   * injector.add([MyService]);
   *
   * // Add with configuration
   * injector.add([ILogger, { useClass: ConsoleLogger }]);
   *
   * // Add a pre-created instance
   * const config = { apiUrl: 'https://api.example.com' };
   * injector.add([IConfig, config]);
   * ```
   */
  add<T>(dependency: DependencyOrInstance<T>): void;
  /**
   * Replace an existing dependency registration.
   *
   * Use this to swap out an implementation, typically for testing purposes.
   * Throws an error if the dependency has already been instantiated.
   *
   * @param dependency - A tuple of `[Identifier, DependencyItem]` to replace the existing registration.
   *
   * @throws {AddDependencyAfterResolutionError} If the dependency is already resolved.
   *
   * @example
   * ```typescript
   * // In tests, replace a real service with a mock
   * injector.replace([IHttpClient, { useClass: MockHttpClient }]);
   * ```
   */
  replace<T>(dependency: DependencyPair<T>): void;
  /**
   * Remove a dependency registration from the injector.
   *
   * Throws an error if the dependency has already been instantiated.
   *
   * @param identifier - The identifier of the dependency to remove.
   *
   * @throws {DeleteDependencyAfterResolutionError} If the dependency is already resolved.
   *
   * @example
   * ```typescript
   * injector.delete(ITemporaryService);
   * ```
   */
  delete<T>(identifier: DependencyIdentifier<T>): void;
  /**
   * Execute a function with controlled access to the injector.
   *
   * The callback receives an `IAccessor` that provides limited access to
   * the injector's `get` and `has` methods. This is useful for service locator
   * patterns or when you need to resolve dependencies dynamically.
   *
   * @param cb - The function to execute. Receives an accessor and any additional arguments.
   * @param args - Additional arguments to pass to the callback.
   * @returns The return value of the callback function.
   *
   * @example
   * ```typescript
   * const result = injector.invoke((accessor, multiplier) => {
   *   const calc = accessor.get(ICalculator);
   *   return calc.compute() * multiplier;
   * }, 2);
   * ```
   */
  invoke<T, P extends any[] = []>(cb: (accessor: IAccessor, ...args: P) => T, ...args: P): T;
  /**
   * Check if a dependency is registered in this injector or any parent injector.
   *
   * @param id - The identifier of the dependency to check.
   * @returns `true` if the dependency is registered, `false` otherwise.
   *
   * @example
   * ```typescript
   * if (injector.has(IOptionalFeature)) {
   *   const feature = injector.get(IOptionalFeature);
   *   feature.enable();
   * }
   * ```
   */
  has<T>(id: DependencyIdentifier<T>): boolean;
  get<T>(id: DependencyIdentifier<T>, lookUp?: LookUp): T;
  get<T>(id: DependencyIdentifier<T>, quantity: Quantity.MANY, lookUp?: LookUp): T[];
  get<T>(id: DependencyIdentifier<T>, quantity: Quantity.OPTIONAL, lookUp?: LookUp): T | null;
  get<T>(id: DependencyIdentifier<T>, quantity: Quantity.REQUIRED, lookUp?: LookUp): T;
  get<T>(id: DependencyIdentifier<T>, quantity?: Quantity, lookUp?: LookUp): T[] | T | null;
  get<T>(id: DependencyIdentifier<T>, quantityOrLookup?: Quantity | LookUp, lookUp?: LookUp): T[] | T | null;
  private _get;
  /**
   * Get a dependency in the async way.
   */
  getAsync<T>(id: DependencyIdentifier<T>): Promise<T>;
  /**
   * Create an instance of a class with its dependencies injected.
   *
   * Unlike `get()`, the created instance is NOT cached by the injector.
   * Each call creates a new instance. You can also pass custom arguments
   * that will be passed before the injected dependencies.
   *
   * @param ctor - The class constructor to instantiate.
   * @param customArgs - Custom arguments to pass before injected dependencies.
   * @returns A new instance of the class.
   *
   * @example
   * ```typescript
   * class RequestHandler {
   *   constructor(
   *     requestId: string,           // Custom arg
   *     @Inject(ILogger) logger: ILogger  // Injected
   *   ) {}
   * }
   *
   * // Create instance with custom requestId
   * const handler = injector.createInstance(RequestHandler, 'req-123');
   * ```
   */
  createInstance<T extends unknown[], U extends unknown[], C>(ctor: new (...args: [...T, ...U]) => C, ...customArgs: T): C;
  private _resolveDependency;
  private _resolveExisting;
  private _resolveValueDependency;
  private _resolveClass;
  private _resolveClassImpl;
  private _resolveFactory;
  private _resolveAsync;
  private _resolveAsyncImpl;
  private getValue;
  private createDependency;
  private markNewResolution;
  private markResolutionCompleted;
  private _ensureInjectorNotDisposed;
}
//#endregion
//#region src/injectSelf.d.ts
interface InjectSelfDecorator {
  (): any;
  new (): InjectSelfDecorator;
}
/**
 * A parameter decorator that injects the current Injector instance itself.
 *
 * This allows a class to access the injector that created it, which can be
 * useful for dynamic dependency resolution or creating child injectors.
 *
 * The injector is looked up with `LookUp.SELF`, meaning only the current
 * injector (not parent injectors) will be returned.
 *
 * @example
 * ```typescript
 * class ServiceFactory {
 *   constructor(@InjectSelf() private injector: Injector) {}
 *
 *   createService<T>(id: DependencyIdentifier<T>): T {
 *     return this.injector.createInstance(id);
 *   }
 *
 *   createChildScope(deps: Dependency[]): Injector {
 *     return this.injector.createChild(deps);
 *   }
 * }
 * ```
 */
declare const InjectSelf: InjectSelfDecorator;
//#endregion
export { AsyncDependencyItem, AsyncHook, ClassDependencyItem, Ctor, Dependency, DependencyIdentifier, DependencyItem, DependencyPair, FactoryDependencyItem, IAccessor, IDisposable, IdentifierDecorator, Inject, InjectSelf, Injector, LookUp, Many, Optional, Quantity, RediError, Self, SkipSelf, SyncDependencyItem, ValueDependencyItem, WithNew, createIdentifier, forwardRef, isAsyncDependencyItem, isAsyncHook, isClassDependencyItem, isCtor, isDisposable, isFactoryDependencyItem, isValueDependencyItem, setDependencies };
//# sourceMappingURL=index.d.ts.map