import { InjectionToken } from '@nestjs/common';
import { Controller, ForwardReference, Injectable, Type } from '@nestjs/common/interfaces';
import { ContextId, InstancePerContext, InstanceWrapper, PropertyMetadata } from './instance-wrapper';
import { Module } from './module';
import { SettlementSignal } from './settlement-signal';
/**
 * The type of an injectable dependency
 */
export type InjectorDependency = InjectionToken;
/**
 * The property-based dependency
 */
export interface PropertyDependency {
    key: symbol | string;
    name: InjectorDependency;
    isOptional?: boolean;
    instance?: any;
}
/**
 * Context of a dependency which gets injected by
 * the injector
 */
export interface InjectorDependencyContext {
    /**
     * The name of the property key (property-based injection)
     */
    key?: string | symbol;
    /**
     * The function itself, the name of the function, or injection token.
     */
    name?: Function | string | symbol;
    /**
     * The index of the dependency which gets injected
     * from the dependencies array
     */
    index?: number;
    /**
     * The dependency array which gets injected
     */
    dependencies?: InjectorDependency[];
}
export declare class Injector {
    private readonly options?;
    private logger;
    private readonly instanceDecorator;
    constructor(options?: {
        /**
         * Whether to enable preview mode.
         */
        preview: boolean;
        /**
         * Function to decorate a freshly created instance.
         */
        instanceDecorator?: (target: unknown) => unknown;
    } | undefined);
    loadPrototype<T>({ token }: InstanceWrapper<T>, collection: Map<InjectionToken, InstanceWrapper<T>>, contextId?: ContextId): void;
    loadInstance<T>(wrapper: InstanceWrapper<T>, collection: Map<InjectionToken, InstanceWrapper>, moduleRef: Module, contextId?: ContextId, inquirer?: InstanceWrapper): Promise<void>;
    loadMiddleware(wrapper: InstanceWrapper, collection: Map<InjectionToken, InstanceWrapper>, moduleRef: Module, contextId?: ContextId, inquirer?: InstanceWrapper): Promise<void>;
    loadController(wrapper: InstanceWrapper<Controller>, moduleRef: Module, contextId?: ContextId): Promise<void>;
    loadInjectable<T = any>(wrapper: InstanceWrapper<T>, moduleRef: Module, contextId?: ContextId, inquirer?: InstanceWrapper): Promise<void>;
    loadProvider(wrapper: InstanceWrapper<Injectable>, moduleRef: Module, contextId?: ContextId, inquirer?: InstanceWrapper): Promise<void>;
    applySettlementSignal<T>(instancePerContext: InstancePerContext<T>, host: InstanceWrapper<T>): SettlementSignal;
    resolveConstructorParams<T>(wrapper: InstanceWrapper<T>, moduleRef: Module, inject: InjectorDependency[] | undefined, callback: (args: unknown[]) => void | Promise<void>, contextId?: ContextId, inquirer?: InstanceWrapper, parentInquirer?: InstanceWrapper): Promise<void>;
    getClassDependencies<T>(wrapper: InstanceWrapper<T>): [InjectorDependency[], number[]];
    getFactoryProviderDependencies<T>(wrapper: InstanceWrapper<T>): [InjectorDependency[], number[]];
    reflectConstructorParams<T>(type: Type<T>): any[];
    reflectOptionalParams<T>(type: Type<T>): any[];
    reflectSelfParams<T>(type: Type<T>): any[];
    resolveSingleParam<T>(wrapper: InstanceWrapper<T>, param: Type<any> | string | symbol, dependencyContext: InjectorDependencyContext, moduleRef: Module, contextId?: ContextId, inquirer?: InstanceWrapper, keyOrIndex?: symbol | string | number): Promise<InstanceWrapper<any>>;
    resolveParamToken<T>(wrapper: InstanceWrapper<T>, param: Type<any> | string | symbol | ForwardReference): any;
    resolveComponentWrapper<T>(moduleRef: Module, token: InjectionToken, dependencyContext: InjectorDependencyContext, wrapper: InstanceWrapper<T>, contextId?: ContextId, inquirer?: InstanceWrapper, keyOrIndex?: symbol | string | number): Promise<InstanceWrapper>;
    resolveComponentHost<T>(moduleRef: Module, instanceWrapper: InstanceWrapper<T | Promise<T>>, contextId?: ContextId, inquirer?: InstanceWrapper): Promise<InstanceWrapper>;
    lookupComponent<T = any>(providers: Map<Function | string | symbol, InstanceWrapper>, moduleRef: Module, dependencyContext: InjectorDependencyContext, wrapper: InstanceWrapper<T>, contextId?: ContextId, inquirer?: InstanceWrapper, keyOrIndex?: symbol | string | number): Promise<InstanceWrapper<T>>;
    lookupComponentInParentModules<T = any>(dependencyContext: InjectorDependencyContext, moduleRef: Module, wrapper: InstanceWrapper<T>, contextId?: ContextId, inquirer?: InstanceWrapper, keyOrIndex?: symbol | string | number): Promise<any>;
    lookupComponentInImports(moduleRef: Module, name: InjectionToken, wrapper: InstanceWrapper, moduleRegistry?: Set<string>, contextId?: ContextId, inquirer?: InstanceWrapper, keyOrIndex?: symbol | string | number, isTraversing?: boolean): Promise<any>;
    resolveProperties<T>(wrapper: InstanceWrapper<T>, moduleRef: Module, inject?: InjectorDependency[], contextId?: ContextId, inquirer?: InstanceWrapper, parentInquirer?: InstanceWrapper): Promise<PropertyDependency[]>;
    reflectProperties<T>(type: Type<T>): PropertyDependency[];
    applyProperties<T = any>(instance: T, properties: PropertyDependency[]): void;
    instantiateClass<T = any>(instances: any[], wrapper: InstanceWrapper, targetMetatype: InstanceWrapper, contextId?: ContextId, inquirer?: InstanceWrapper): Promise<T>;
    loadPerContext<T = any>(instance: T, moduleRef: Module, collection: Map<InjectionToken, InstanceWrapper>, ctx: ContextId, wrapper?: InstanceWrapper): Promise<T>;
    loadEnhancersPerContext(wrapper: InstanceWrapper, ctx: ContextId, inquirer?: InstanceWrapper): Promise<void>;
    loadCtorMetadata(metadata: InstanceWrapper<any>[], contextId: ContextId, inquirer?: InstanceWrapper, parentInquirer?: InstanceWrapper): Promise<any[]>;
    loadPropertiesMetadata(metadata: PropertyMetadata[], contextId: ContextId, inquirer?: InstanceWrapper): Promise<PropertyDependency[]>;
    private getInquirerId;
    /**
     * For nested TRANSIENT dependencies (TRANSIENT -> TRANSIENT) in non-static contexts,
     * returns parentInquirer to ensure each parent TRANSIENT gets its own instance.
     * This is necessary because in REQUEST/DURABLE scopes, the same TRANSIENT wrapper
     * can be used by multiple parents, causing nested TRANSIENTs to be shared incorrectly.
     * For non-TRANSIENT -> TRANSIENT, returns inquirer (current wrapper being created).
     */
    private getEffectiveInquirer;
    private resolveScopedComponentHost;
    private isInquirerRequest;
    private isInquirer;
    protected addDependencyMetadata(keyOrIndex: symbol | string | number, hostWrapper: InstanceWrapper, instanceWrapper: InstanceWrapper): void;
    private getTokenName;
    private printResolvingDependenciesLog;
    private printLookingForProviderLog;
    private printFoundInModuleLog;
    private isDebugMode;
    private getContextId;
    private getNowTimestamp;
}
