import { Subject } from 'rxjs' ; import { first } from 'rxjs/operators' ; import { DiscoveredPlugin , PluginOpaqueId } from '../../server' ; import { PluginInitializerContext } from './plugin_context' ; import { read } from './plugin_reader' ; import { CoreStart , CoreSetup } from '..' ; public export interface Plugin < TSetup = void , TStart = void , TPluginsSetup extends object = object , TPluginsStart extends object = object > { setup ( core , plugins ) : TSetup | Promise < TSetup > ; start ( core , plugins ) : TStart | Promise < TStart > ; stop ? ( ) : void ; } public export type PluginInitializer < TSetup , TStart , TPluginsSetup extends object = object , TPluginsStart extends object = object > = ( core : PluginInitializerContext ) => Plugin < TSetup , TStart , TPluginsSetup , TPluginsStart > ; internal export class PluginWrapper < TSetup = unknown , TStart = unknown , TPluginsSetup extends object = object , TPluginsStart extends object = object > { public readonly name : DiscoveredPlugin [ 'id' ] ; public readonly configPath : DiscoveredPlugin [ 'configPath' ] ; public readonly requiredPlugins : DiscoveredPlugin [ 'requiredPlugins' ] ; public readonly optionalPlugins : DiscoveredPlugin [ 'optionalPlugins' ] ; private instance ? : Plugin < TSetup , TStart , TPluginsSetup , TPluginsStart > ; private readonly startDependencies$ = new Subject < [ CoreStart , TPluginsStart , TStart ] > ( ) ; public readonly startDependencies = this . startDependencies$ . pipe ( first ( ) ) . toPromise ( ) ; constructor ( public readonly discoveredPlugin , public readonly opaqueId , private readonly initializerContext ) { this . name = discoveredPlugin . id ; this . configPath = discoveredPlugin . configPath ; this . requiredPlugins = discoveredPlugin . requiredPlugins ; this . optionalPlugins = discoveredPlugin . optionalPlugins ; } param setupContext param plugins public async setup ( setupContext , plugins ) { this . instance = await this . createPluginInstance ( ) ; return await this . instance . setup ( setupContext , plugins ) ; } param startContext param plugins public async start ( startContext , plugins ) { if ( this . instance === undefined ) { throw new Error ( `Plugin "${ this . name }" can't be started since it isn't set up.` ) ; } const startContract = await this . instance . start ( startContext , plugins ) ; this . startDependencies$ . next ( [ startContext , plugins , startContract ] ) ; return startContract ; } /**
     * Calls optional `stop` function exposed by the plugin initializer.
     */ public stop ( ) { if ( this . instance === undefined ) { throw new Error ( `Plugin "${ this . name }" can't be stopped since it isn't set up.` ) ; } if ( typeof this . instance . stop === 'function' ) { this . instance . stop ( ) ; } this . instance = undefined ; } private async createPluginInstance ( ) { const initializer = read ( this . name ) as PluginInitializer < TSetup , TStart , TPluginsSetup , TPluginsStart > ; const instance = initializer ( this . initializerContext ) ; if ( typeof instance . setup !== 'function' ) { throw new Error ( `Instance of plugin "${ this . name }" does not define "setup" function.` ) ; } else if ( typeof instance . start !== 'function' ) { throw new Error ( `Instance of plugin "${ this . name }" does not define "start" function.` ) ; } return instance ; } }