import { BackendFeature } from '../../types';
/**
 * TODO
 *
 * @public
 */
export type ServiceRef<TService, TScope extends 'root' | 'plugin' = 'root' | 'plugin'> = {
    id: string;
    /**
     * This determines the scope at which this service is available.
     *
     * Root scoped services are available to all other services but
     * may only depend on other root scoped services.
     *
     * Plugin scoped services are only available to other plugin scoped
     * services but may depend on all other services.
     */
    scope: TScope;
    /**
     * Utility for getting the type of the service, using `typeof serviceRef.T`.
     * Attempting to actually read this value will result in an exception.
     */
    T: TService;
    toString(): string;
    $$type: '@backstage/ServiceRef';
};
/** @public */
export interface ServiceFactory<TService = unknown, TScope extends 'plugin' | 'root' = 'plugin' | 'root'> extends BackendFeature {
    service: ServiceRef<TService, TScope>;
}
/**
 * Represents either a {@link ServiceFactory} or a function that returns one.
 *
 * @public
 */
export type ServiceFactoryOrFunction = ServiceFactory | (() => ServiceFactory);
/** @public */
export interface ServiceRefConfig<TService, TScope extends 'root' | 'plugin'> {
    id: string;
    scope?: TScope;
    defaultFactory?: (service: ServiceRef<TService, TScope>) => Promise<ServiceFactoryOrFunction>;
}
/**
 * Creates a new service definition. This overload is used to create plugin scoped services.
 *
 * @public
 */
export declare function createServiceRef<TService>(config: ServiceRefConfig<TService, 'plugin'>): ServiceRef<TService, 'plugin'>;
/**
 * Creates a new service definition. This overload is used to create root scoped services.
 *
 * @public
 */
export declare function createServiceRef<TService>(config: ServiceRefConfig<TService, 'root'>): ServiceRef<TService, 'root'>;
/** @ignore */
type ServiceRefsToInstances<T extends {
    [key in string]: ServiceRef<unknown>;
}, TScope extends 'root' | 'plugin' = 'root' | 'plugin'> = {
    [key in keyof T as T[key]['scope'] extends TScope ? key : never]: T[key]['T'];
};
/** @public */
export interface RootServiceFactoryConfig<TService, TImpl extends TService, TDeps extends {
    [name in string]: ServiceRef<unknown>;
}> {
    service: ServiceRef<TService, 'root'>;
    deps: TDeps;
    factory(deps: ServiceRefsToInstances<TDeps, 'root'>): TImpl | Promise<TImpl>;
}
/** @public */
export interface PluginServiceFactoryConfig<TService, TContext, TImpl extends TService, TDeps extends {
    [name in string]: ServiceRef<unknown>;
}> {
    service: ServiceRef<TService, 'plugin'>;
    deps: TDeps;
    createRootContext?(deps: ServiceRefsToInstances<TDeps, 'root'>): TContext | Promise<TContext>;
    factory(deps: ServiceRefsToInstances<TDeps>, context: TContext): TImpl | Promise<TImpl>;
}
/**
 * Creates a root scoped service factory without options.
 *
 * @public
 * @param config - The service factory configuration.
 */
export declare function createServiceFactory<TService, TImpl extends TService, TDeps extends {
    [name in string]: ServiceRef<unknown, 'root'>;
}, TOpts extends object | undefined = undefined>(config: RootServiceFactoryConfig<TService, TImpl, TDeps>): () => ServiceFactory<TService, 'root'>;
/**
 * Creates a root scoped service factory with optional options.
 *
 * @public
 * @param config - The service factory configuration.
 */
export declare function createServiceFactory<TService, TImpl extends TService, TDeps extends {
    [name in string]: ServiceRef<unknown, 'root'>;
}, TOpts extends object | undefined = undefined>(config: (options?: TOpts) => RootServiceFactoryConfig<TService, TImpl, TDeps>): (options?: TOpts) => ServiceFactory<TService, 'root'>;
/**
 * Creates a plugin scoped service factory without options.
 *
 * @public
 * @param config - The service factory configuration.
 */
export declare function createServiceFactory<TService, TImpl extends TService, TDeps extends {
    [name in string]: ServiceRef<unknown>;
}, TContext = undefined, TOpts extends object | undefined = undefined>(config: PluginServiceFactoryConfig<TService, TContext, TImpl, TDeps>): () => ServiceFactory<TService, 'plugin'>;
/**
 * Creates a plugin scoped service factory with optional options.
 *
 * @public
 * @param config - The service factory configuration.
 */
export declare function createServiceFactory<TService, TImpl extends TService, TDeps extends {
    [name in string]: ServiceRef<unknown>;
}, TContext = undefined, TOpts extends object | undefined = undefined>(config: (options?: TOpts) => PluginServiceFactoryConfig<TService, TContext, TImpl, TDeps>): (options?: TOpts) => ServiceFactory<TService, 'plugin'>;
export {};
