import { Atom, type Registry } from '@effect-atom/atom-react';
import * as Effect from 'effect/Effect';
import { type MaybePromise } from '@dxos/util';
import { type ActivationEvent } from './events';
declare const InterfaceDefTypeId: unique symbol;
/**
 * The interface definition of a capability.
 */
export type InterfaceDef<T> = {
    [InterfaceDefTypeId]: T;
    identifier: string;
};
export declare namespace InterfaceDef {
    type Implementation<I extends InterfaceDef<any>> = I extends InterfaceDef<infer T> ? T : never;
}
/**
 * Helper to define the interface of a capability.
 */
export declare const defineCapability: <T>(identifier: string) => InterfaceDef<T>;
/**
 * A unique string identifier with a Typescript type associated with it.
 * When a capability is contributed to the application an implementation of the interface is provided.
 */
export type Capability<T> = {
    /**
     * The interface definition of the capability.
     */
    readonly interface: InterfaceDef<T>;
    /**
     * The implementation of the capability.
     */
    readonly implementation: T;
    /**
     * Called when the capability is deactivated.
     */
    readonly deactivate?: () => MaybePromise<void> | Effect.Effect<void, Error>;
};
export type AnyCapability = Capability<any>;
type PluginsContextOptions = {
    registry: Registry.Registry;
    activate: (event: ActivationEvent) => Effect.Effect<boolean, Error>;
    reset: (event: ActivationEvent) => Effect.Effect<boolean, Error>;
};
/**
 * Helper to define the implementation of a capability.
 */
export declare const contributes: <I extends InterfaceDef<any>>(interfaceDef: I, implementation: Capability<InterfaceDef.Implementation<I>>["implementation"], deactivate?: Capability<InterfaceDef.Implementation<I>>["deactivate"]) => Capability<I>;
type LoadCapability<T, U> = () => Promise<{
    default: (props: T) => MaybePromise<Capability<U>>;
}>;
type LoadCapabilities<T> = () => Promise<{
    default: (props: T) => MaybePromise<AnyCapability[]>;
}>;
type LazyCapability<T, U> = (props?: T) => Promise<() => Promise<Capability<U> | AnyCapability[]>>;
/**
 * Helper to define a lazily loaded implementation of a capability.
 */
export declare const lazy: <T, U>(c: LoadCapability<T, U> | LoadCapabilities<T>) => LazyCapability<T, U>;
/**
 * Facilitates the dependency injection between [plugin modules](#pluginmodule) by allowing them contribute and request capabilities from each other.
 * It tracks the capabilities that are contributed in an in-memory live object.
 * This allows the application to subscribe to this state and incorporate plugins which are added dynamically.
 */
export declare class PluginContext {
    private readonly _registry;
    private readonly _capabilityImpls;
    readonly _capabilities: (arg: string) => Atom.Atom<unknown[]>;
    readonly _capability: (arg: string) => Atom.Atom<unknown>;
    /**
     * Activates plugins based on the activation event.
     * @param event The activation event.
     * @returns Whether the activation was successful.
     */
    readonly activate: PluginsContextOptions['activate'];
    /**
     * Re-activates the modules that were activated by the event.
     * @param event The activation event.
     * @returns Whether the reset was successful.
     */
    readonly reset: PluginsContextOptions['reset'];
    constructor({ registry, activate, reset }: PluginsContextOptions);
    /**
     * Get the Atom reference to the available capabilities for a given interface.
     * Primarily useful for deriving other Atom values based on the capabilities or
     * for subscribing to changes in the capabilities.
     * @returns An atom reference to the available capabilities.
     */
    capabilities<T>(interfaceDef: InterfaceDef<T>): Atom.Atom<T[]>;
    /**
     * Get the Atom reference to the available capabilities for a given interface.
     * Primarily useful for deriving other Atom values based on the capability or
     * for subscribing to changes in the capability.
     * @returns An atom reference to the available capability.
     * @throws If no capability is found.
     */
    capability<T>(interfaceDef: InterfaceDef<T>): Atom.Atom<T>;
    /**
     * Get capabilities from the plugin context.
     * @returns An array of capabilities.
     */
    getCapabilities<T>(interfaceDef: InterfaceDef<T>): T[];
    /**
     * Requests a single capability from the plugin context.
     * @returns The capability.
     * @throws If no capability is found.
     */
    getCapability<T>(interfaceDef: InterfaceDef<T>): T;
    /**
     * Waits for a capability to be available.
     * @returns The capability.
     */
    waitForCapability<T>(interfaceDef: InterfaceDef<T>): Promise<T>;
    activatePromise(event: ActivationEvent): Promise<boolean>;
    resetPromise(event: ActivationEvent): Promise<boolean>;
}
export {};
//# sourceMappingURL=capabilities.d.ts.map