import { Token } from './token';
/**
 * A user-defined application plugin.
 *
 * @typeParam T - The type for the application.
 *
 * @typeParam U - The service type, if the plugin `provides` one.
 *
 * #### Notes
 * Plugins are the foundation for building an extensible application.
 *
 * Plugins consume and provide "services", which are nothing more than
 * concrete implementations of interfaces and/or abstract types.
 *
 * Unlike regular imports and exports, which tie the service consumer
 * to a particular implementation of the service, plugins decouple the
 * service producer from the service consumer, allowing an application
 * to be easily customized by third parties in a type-safe fashion.
 */
export interface IPlugin<T, U> {
    /**
     * The human readable ID of the plugin.
     *
     * #### Notes
     * This must be unique within an application.
     */
    id: string;
    /**
     * Plugin description.
     *
     * #### Notes
     * This can be used to provide user documentation on the feature
     * brought by a plugin.
     */
    description?: string;
    /**
     * Whether the plugin should be activated on application start or waiting for being
     * required. If the value is 'defer' then the plugin should be activated only after
     * the application is started.
     *
     * #### Notes
     * The default is `false`.
     */
    autoStart?: boolean | 'defer';
    /**
     * The types of required services for the plugin, if any.
     *
     * #### Notes
     * These tokens correspond to the services that are required by
     * the plugin for correct operation.
     *
     * When the plugin is activated, a concrete instance of each type
     * will be passed to the `activate()` function, in the order they
     * are specified in the `requires` array.
     */
    requires?: Token<any>[];
    /**
     * The types of optional services for the plugin, if any.
     *
     * #### Notes
     * These tokens correspond to the services that can be used by the
     * plugin if available, but are not necessarily required.
     *
     * The optional services will be passed to the `activate()` function
     * following all required services. If an optional service cannot be
     * resolved, `null` will be passed in its place.
     */
    optional?: Token<any>[];
    /**
     * The type of service provided by the plugin, if any.
     *
     * #### Notes
     * This token corresponds to the service exported by the plugin.
     *
     * When the plugin is activated, the return value of `activate()`
     * is used as the concrete instance of the type.
     */
    provides?: Token<U> | null;
    /**
     * A function invoked to activate the plugin.
     *
     * @param app - The application provided by {@link PluginRegistry.application} .
     *
     * @param args - The services specified by the `requires` property.
     *
     * @returns The provided service, or a promise to the service.
     *
     * #### Notes
     * This function will be called whenever the plugin is manually
     * activated, or when another plugin being activated requires
     * the service it provides.
     *
     * This function will not be called unless all of its required
     * services can be fulfilled.
     */
    activate: (app: T, ...args: any[]) => U | Promise<U>;
    /**
     * A function invoked to deactivate the plugin.
     *
     * @param app - The application {@link PluginRegistry.application} .
     *
     * @param args - The services specified by the `requires` property.
     */
    deactivate?: ((app: T, ...args: any[]) => void | Promise<void>) | null;
}
/**
 * Plugin registry.
 */
export declare class PluginRegistry<T = any> {
    constructor(options?: PluginRegistry.IOptions);
    /**
     * The application object.
     *
     * It will be provided as first argument to the
     * plugins activation and deactivation functions.
     *
     * It can only be set once.
     *
     * By default, it is `null`.
     */
    get application(): T;
    set application(v: T);
    /**
     * The list of all the deferred plugins.
     */
    get deferredPlugins(): string[];
    /**
     * Get a plugin description.
     *
     * @param id - The ID of the plugin of interest.
     *
     * @returns The plugin description.
     */
    getPluginDescription(id: string): string;
    /**
     * Test whether a plugin is registered with the application.
     *
     * @param id - The ID of the plugin of interest.
     *
     * @returns `true` if the plugin is registered, `false` otherwise.
     */
    hasPlugin(id: string): boolean;
    /**
     * Test whether a plugin is activated with the application.
     *
     * @param id - The ID of the plugin of interest.
     *
     * @returns `true` if the plugin is activated, `false` otherwise.
     */
    isPluginActivated(id: string): boolean;
    /**
     * List the IDs of the plugins registered with the application.
     *
     * @returns A new array of the registered plugin IDs.
     */
    listPlugins(): string[];
    /**
     * Register a plugin with the application.
     *
     * @param plugin - The plugin to register.
     *
     * #### Notes
     * An error will be thrown if a plugin with the same ID is already
     * registered, or if the plugin has a circular dependency.
     *
     * If the plugin provides a service which has already been provided
     * by another plugin, the new service will override the old service.
     */
    registerPlugin(plugin: IPlugin<T, any>): void;
    /**
     * Register multiple plugins with the application.
     *
     * @param plugins - The plugins to register.
     *
     * #### Notes
     * This calls `registerPlugin()` for each of the given plugins.
     */
    registerPlugins(plugins: IPlugin<T, any>[]): void;
    /**
     * Deregister a plugin with the application.
     *
     * @param id - The ID of the plugin of interest.
     *
     * @param force - Whether to deregister the plugin even if it is active.
     */
    deregisterPlugin(id: string, force?: boolean): void;
    /**
     * Activate the plugin with the given ID.
     *
     * @param id - The ID of the plugin of interest.
     *
     * @returns A promise which resolves when the plugin is activated
     *   or rejects with an error if it cannot be activated.
     */
    activatePlugin(id: string): Promise<void>;
    /**
     * Activate all the deferred plugins.
     *
     * @returns A promise which will resolve when each plugin is activated
     * or rejects with an error if one cannot be activated.
     */
    activatePlugins(kind: 'startUp' | 'defer', options?: PluginRegistry.IStartOptions): Promise<void>;
    /**
     * Deactivate the plugin and its downstream dependents if and only if the
     * plugin and its dependents all support `deactivate`.
     *
     * @param id - The ID of the plugin of interest.
     *
     * @returns A list of IDs of downstream plugins deactivated with this one.
     */
    deactivatePlugin(id: string): Promise<string[]>;
    /**
     * Resolve a required service of a given type.
     *
     * @param token - The token for the service type of interest.
     *
     * @returns A promise which resolves to an instance of the requested
     *   service, or rejects with an error if it cannot be resolved.
     *
     * #### Notes
     * Services are singletons. The same instance will be returned each
     * time a given service token is resolved.
     *
     * If the plugin which provides the service has not been activated,
     * resolving the service will automatically activate the plugin.
     *
     * User code will not typically call this method directly. Instead,
     * the required services for the user's plugins will be resolved
     * automatically when the plugin is activated.
     */
    resolveRequiredService<U>(token: Token<U>): Promise<U>;
    /**
     * Resolve an optional service of a given type.
     *
     * @param token - The token for the service type of interest.
     *
     * @returns A promise which resolves to an instance of the requested
     *   service, or `null` if it cannot be resolved.
     *
     * #### Notes
     * Services are singletons. The same instance will be returned each
     * time a given service token is resolved.
     *
     * If the plugin which provides the service has not been activated,
     * resolving the service will automatically activate the plugin.
     *
     * User code will not typically call this method directly. Instead,
     * the optional services for the user's plugins will be resolved
     * automatically when the plugin is activated.
     */
    resolveOptionalService<U>(token: Token<U>): Promise<U | null>;
    private _application;
    private _validatePlugin;
    private _plugins;
    private _services;
}
/**
 * PluginRegistry namespace
 */
export declare namespace PluginRegistry {
    /**
     * PluginRegistry constructor options.
     */
    interface IOptions {
        /**
         * Validate that a plugin is allowed to be registered.
         *
         * Default is `() => true`.
         *
         * @param plugin The plugin to validate
         * @returns Whether the plugin can be registered or not.
         *
         * #### Notes
         * We recommend you print a console message with the reason
         * a plugin is invalid.
         */
        validatePlugin?: (plugin: IPlugin<any, any>) => boolean;
    }
    /**
     * An options object for application startup.
     */
    interface IStartOptions {
        /**
         * The plugins to activate on startup.
         *
         * #### Notes
         * These will be *in addition* to any `autoStart` plugins.
         */
        startPlugins?: string[];
        /**
         * The plugins to **not** activate on startup.
         *
         * #### Notes
         * This will override `startPlugins` and any `autoStart` plugins.
         */
        ignorePlugins?: string[];
    }
}
