import type { AnyToken, AsyncServiceFactory, AsyncToken, CreateScopeOptions, Lifetime, ServiceFactory, SyncToken } from './types.js';
/**
 * Thrown when a method is called on an injector that has already been disposed.
 */
export declare class InjectorDisposedError extends Error {
    constructor();
}
/**
 * Thrown when a factory depends on itself (directly or transitively) during
 * instantiation.
 */
export declare class CircularDependencyError extends Error {
    readonly path: readonly string[];
    constructor(path: readonly string[]);
}
/**
 * Thrown when a singleton-lifetime service attempts to depend on a non-singleton
 * service, or a scoped service attempts to depend on a transient.
 */
export declare class InvalidLifetimeDependencyError extends Error {
    readonly parentName: string;
    readonly parentLifetime: Lifetime;
    readonly childName: string;
    readonly childLifetime: Lifetime;
    constructor(parentName: string, parentLifetime: Lifetime, childName: string, childLifetime: Lifetime);
}
/**
 * Thrown when attempting to resolve an async token via the synchronous
 * {@link Injector.get} method. In well-typed call sites this case is caught at
 * compile time by {@link Injector.get}'s signature; the runtime check exists
 * as a defense for dynamically-constructed tokens.
 */
export declare class AsyncTokenInSyncContextError extends Error {
    readonly tokenName: string;
    constructor(tokenName: string);
}
/**
 * The dependency injection container. Created via {@link createInjector} or
 * {@link Injector.createScope}. Manages service resolution, caching, and
 * disposal across a hierarchical scope tree.
 */
export declare class Injector implements AsyncDisposable {
    readonly parent: Injector | null;
    readonly owner: unknown;
    private readonly cache;
    private readonly bindings;
    private readonly disposeCallbacks;
    private isDisposed;
    constructor(options?: {
        parent?: Injector;
        owner?: unknown;
    });
    private ensureLive;
    private rootInjector;
    private ownerForLifetime;
    private findCached;
    private findFactory;
    private buildContext;
    /**
     * Resolves a sync token. Throws {@link InjectorDisposedError} if the
     * injector is already disposed and {@link AsyncTokenInSyncContextError} if
     * a runtime-async token slips past the compile-time check.
     */
    get<TService>(token: SyncToken<TService>): TService;
    /**
     * Resolves a sync or async token. Sync tokens are wrapped in a resolved
     * promise. Synchronous failures (disposed injector, sync-throwing async
     * factory) are normalised to a rejected promise so callers can rely on
     * `.rejects` / `.catch` uniformly.
     */
    getAsync<TService>(token: AnyToken<TService>): Promise<TService>;
    private resolveSync;
    private resolveAsync;
    private consumeCached;
    private consumeCachedAsync;
    private pushResolving;
    private popResolving;
    private instantiateSync;
    private instantiateAsync;
    /**
     * Installs a factory override for `token` on the injector that would own its
     * cached instance (root for singleton, this injector for scoped/transient).
     * Any cached entry for the token on that injector is dropped so the next
     * resolution uses the new factory.
     *
     * Scope caveat: a `scoped` bind applies only to the injector it was called
     * on. Descendant scopes each own their own cache and resolve scoped tokens
     * against `token.factory` unless they also call `bind`. Bind at the highest
     * scope whose cache you want the override to populate — usually the same
     * scope that will call `injector.get(token)`.
     */
    bind<TService, TLifetime extends Lifetime>(token: SyncToken<TService, TLifetime>, factory: ServiceFactory<TService>): void;
    bind<TService, TLifetime extends Lifetime>(token: AsyncToken<TService, TLifetime>, factory: AsyncServiceFactory<TService>): void;
    /**
     * Drops any cached entry for `token` on the injector that owns its cached
     * instance. The next resolution will run the factory again. Useful for
     * recovering from cached factory failures or resetting state between tests.
     */
    invalidate<TService>(token: AnyToken<TService>): void;
    /**
     * Returns `true` when `token` has a cache entry (resolved, pending or
     * failed) on the scope that owns its lifetime -- the root injector for
     * singletons, the requesting injector for scoped tokens. Transient
     * tokens are never cached and therefore always report `false`.
     *
     * Useful for bootstrap helpers that must run before a service is first
     * resolved: checking `isResolved` lets them fail loudly instead of
     * silently leaking the previous instance.
     */
    isResolved<TService>(token: AnyToken<TService>): boolean;
    /**
     * Creates a child injector. The child has its own cache and bindings;
     * singleton resolution still walks up to the root. Disposing the child
     * leaves the parent untouched. Disposing the parent disposes all
     * descendants reachable through stored references.
     */
    createScope(options?: CreateScopeOptions): Injector;
    /**
     * Disposes the injector: runs registered `onDispose` callbacks in LIFO
     * order, clears the cache, and marks the injector as disposed. Idempotent —
     * a second call is a no-op so `await using` and manual teardown paths
     * don't have to guard. Errors from callbacks are collected and re-thrown
     * as a single `AggregateError`.
     */
    [Symbol.asyncDispose](): Promise<void>;
}
/**
 * Creates a new root {@link Injector}.
 */
export declare const createInjector: () => Injector;
/**
 * Creates a child scope of `parent`, runs `fn` with it, then disposes the
 * scope — including when `fn` throws. Returns `fn`'s resolved value.
 */
export declare const withScope: <TResult>(parent: Injector, fn: (scope: Injector) => Promise<TResult> | TResult, options?: CreateScopeOptions) => Promise<TResult>;
//# sourceMappingURL=injector.d.ts.map