Add plugin start contract to getStartServices return value (#61216)

* add plugin own contract as third element of getStartServices result

* adapt plugins code

* update tests

* revert unknown to use void again

* update generated doc

* fix UT

* update mock to allow non-object `pluginStartContract`

* add @typeParam documentation
This commit is contained in:
Pierre Gayvallet 2020-03-26 10:49:05 +01:00 committed by GitHub
parent 9d0d3f7a53
commit 468de51153
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 178 additions and 93 deletions

View file

@ -9,5 +9,5 @@
<b>Signature:</b>
```typescript
getStartServices: StartServicesAccessor<TPluginsStart>;
getStartServices: StartServicesAccessor<TPluginsStart, TStart>;
```

View file

@ -9,7 +9,7 @@ Core services exposed to the `Plugin` setup lifecycle
<b>Signature:</b>
```typescript
export interface CoreSetup<TPluginsStart extends object = object>
export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown>
```
## Properties
@ -19,7 +19,7 @@ export interface CoreSetup<TPluginsStart extends object = object>
| [application](./kibana-plugin-core-public.coresetup.application.md) | <code>ApplicationSetup</code> | [ApplicationSetup](./kibana-plugin-core-public.applicationsetup.md) |
| [context](./kibana-plugin-core-public.coresetup.context.md) | <code>ContextSetup</code> | [ContextSetup](./kibana-plugin-core-public.contextsetup.md) |
| [fatalErrors](./kibana-plugin-core-public.coresetup.fatalerrors.md) | <code>FatalErrorsSetup</code> | [FatalErrorsSetup](./kibana-plugin-core-public.fatalerrorssetup.md) |
| [getStartServices](./kibana-plugin-core-public.coresetup.getstartservices.md) | <code>StartServicesAccessor&lt;TPluginsStart&gt;</code> | [StartServicesAccessor](./kibana-plugin-core-public.startservicesaccessor.md) |
| [getStartServices](./kibana-plugin-core-public.coresetup.getstartservices.md) | <code>StartServicesAccessor&lt;TPluginsStart, TStart&gt;</code> | [StartServicesAccessor](./kibana-plugin-core-public.startservicesaccessor.md) |
| [http](./kibana-plugin-core-public.coresetup.http.md) | <code>HttpSetup</code> | [HttpSetup](./kibana-plugin-core-public.httpsetup.md) |
| [injectedMetadata](./kibana-plugin-core-public.coresetup.injectedmetadata.md) | <code>{</code><br/><code> getInjectedVar: (name: string, defaultValue?: any) =&gt; unknown;</code><br/><code> }</code> | exposed temporarily until https://github.com/elastic/kibana/issues/41990 done use \*only\* to retrieve config values. There is no way to set injected values in the new platform. Use the legacy platform API instead. |
| [notifications](./kibana-plugin-core-public.coresetup.notifications.md) | <code>NotificationsSetup</code> | [NotificationsSetup](./kibana-plugin-core-public.notificationssetup.md) |

View file

@ -13,7 +13,7 @@ Setup interface exposed to the legacy platform via the `ui/new_platform` module.
<b>Signature:</b>
```typescript
export interface LegacyCoreSetup extends CoreSetup<any>
export interface LegacyCoreSetup extends CoreSetup<any, any>
```
## Remarks

View file

@ -7,14 +7,14 @@
<b>Signature:</b>
```typescript
setup(core: CoreSetup<TPluginsStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>;
setup(core: CoreSetup<TPluginsStart, TStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| core | <code>CoreSetup&lt;TPluginsStart&gt;</code> | |
| core | <code>CoreSetup&lt;TPluginsStart, TStart&gt;</code> | |
| plugins | <code>TPluginsSetup</code> | |
<b>Returns:</b>

View file

@ -9,5 +9,5 @@ Allows plugins to get access to APIs available in start inside async handlers, s
<b>Signature:</b>
```typescript
export declare type StartServicesAccessor<TPluginsStart extends object = object> = () => Promise<[CoreStart, TPluginsStart]>;
export declare type StartServicesAccessor<TPluginsStart extends object = object, TStart = unknown> = () => Promise<[CoreStart, TPluginsStart, TStart]>;
```

View file

@ -9,5 +9,5 @@
<b>Signature:</b>
```typescript
getStartServices: StartServicesAccessor<TPluginsStart>;
getStartServices: StartServicesAccessor<TPluginsStart, TStart>;
```

View file

@ -9,7 +9,7 @@ Context passed to the plugins `setup` method.
<b>Signature:</b>
```typescript
export interface CoreSetup<TPluginsStart extends object = object>
export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown>
```
## Properties
@ -19,7 +19,7 @@ export interface CoreSetup<TPluginsStart extends object = object>
| [capabilities](./kibana-plugin-core-server.coresetup.capabilities.md) | <code>CapabilitiesSetup</code> | [CapabilitiesSetup](./kibana-plugin-core-server.capabilitiessetup.md) |
| [context](./kibana-plugin-core-server.coresetup.context.md) | <code>ContextSetup</code> | [ContextSetup](./kibana-plugin-core-server.contextsetup.md) |
| [elasticsearch](./kibana-plugin-core-server.coresetup.elasticsearch.md) | <code>ElasticsearchServiceSetup</code> | [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) |
| [getStartServices](./kibana-plugin-core-server.coresetup.getstartservices.md) | <code>StartServicesAccessor&lt;TPluginsStart&gt;</code> | [StartServicesAccessor](./kibana-plugin-core-server.startservicesaccessor.md) |
| [getStartServices](./kibana-plugin-core-server.coresetup.getstartservices.md) | <code>StartServicesAccessor&lt;TPluginsStart, TStart&gt;</code> | [StartServicesAccessor](./kibana-plugin-core-server.startservicesaccessor.md) |
| [http](./kibana-plugin-core-server.coresetup.http.md) | <code>HttpServiceSetup</code> | [HttpServiceSetup](./kibana-plugin-core-server.httpservicesetup.md) |
| [metrics](./kibana-plugin-core-server.coresetup.metrics.md) | <code>MetricsServiceSetup</code> | [MetricsServiceSetup](./kibana-plugin-core-server.metricsservicesetup.md) |
| [savedObjects](./kibana-plugin-core-server.coresetup.savedobjects.md) | <code>SavedObjectsServiceSetup</code> | [SavedObjectsServiceSetup](./kibana-plugin-core-server.savedobjectsservicesetup.md) |

View file

@ -9,5 +9,5 @@ Allows plugins to get access to APIs available in start inside async handlers. P
<b>Signature:</b>
```typescript
export declare type StartServicesAccessor<TPluginsStart extends object = object> = () => Promise<[CoreStart, TPluginsStart]>;
export declare type StartServicesAccessor<TPluginsStart extends object = object, TStart = unknown> = () => Promise<[CoreStart, TPluginsStart, TStart]>;
```

View file

@ -17,7 +17,7 @@
* under the License.
*/
import { Plugin, CoreSetup, AppMountParameters, CoreStart } from 'kibana/public';
import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public';
import { PluginSetupContract as AlertingSetup } from '../../../x-pack/plugins/alerting/public';
import { ChartsPluginStart } from '../../../src/plugins/charts/public';
import { TriggersAndActionsUIPublicPluginSetup } from '../../../x-pack/plugins/triggers_actions_ui/public';
@ -43,17 +43,14 @@ export interface AlertingExamplePublicStartDeps {
export class AlertingExamplePlugin implements Plugin<Setup, Start, AlertingExamplePublicSetupDeps> {
public setup(
core: CoreSetup<AlertingExamplePublicStartDeps>,
core: CoreSetup<AlertingExamplePublicStartDeps, Start>,
{ alerting, triggers_actions_ui }: AlertingExamplePublicSetupDeps
) {
core.application.register({
id: 'AlertingExample',
title: 'Alerting Example',
async mount(params: AppMountParameters) {
const [coreStart, depsStart]: [
CoreStart,
AlertingExamplePublicStartDeps
] = await core.getStartServices();
const [coreStart, depsStart] = await core.getStartServices();
const { renderApp } = await import('./application');
return renderApp(coreStart, depsStart, params);
},

View file

@ -34,7 +34,10 @@ export interface BfetchExplorerStartPlugins {
}
export class BfetchExplorerPlugin implements Plugin {
public setup(core: CoreSetup<BfetchExplorerStartPlugins>, plugins: BfetchExplorerSetupPlugins) {
public setup(
core: CoreSetup<BfetchExplorerStartPlugins, void>,
plugins: BfetchExplorerSetupPlugins
) {
const double = plugins.bfetch.batchedFunction<{ num: number }, { num: number }>({
url: '/bfetch_explorer/double',
});

View file

@ -26,9 +26,18 @@ export {
export { ListContainer, LIST_CONTAINER } from './list_container';
export { TODO_EMBEDDABLE } from './todo';
import { EmbeddableExamplesPlugin } from './plugin';
import {
EmbeddableExamplesPlugin,
EmbeddableExamplesSetupDependencies,
EmbeddableExamplesStartDependencies,
} from './plugin';
export { SearchableListContainer, SEARCHABLE_LIST_CONTAINER } from './searchable_list_container';
export { MULTI_TASK_TODO_EMBEDDABLE } from './multi_task_todo';
export const plugin: PluginInitializer<void, void> = () => new EmbeddableExamplesPlugin();
export const plugin: PluginInitializer<
void,
void,
EmbeddableExamplesSetupDependencies,
EmbeddableExamplesStartDependencies
> = () => new EmbeddableExamplesPlugin();

View file

@ -28,11 +28,11 @@ import {
} from './searchable_list_container';
import { LIST_CONTAINER, ListContainerFactory } from './list_container';
interface EmbeddableExamplesSetupDependencies {
export interface EmbeddableExamplesSetupDependencies {
embeddable: EmbeddableSetup;
}
interface EmbeddableExamplesStartDependencies {
export interface EmbeddableExamplesStartDependencies {
embeddable: EmbeddableStart;
}

View file

@ -21,7 +21,7 @@ import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public';
import { AppPluginStartDependencies } from './types';
export class SearchExplorerPlugin implements Plugin {
public setup(core: CoreSetup<AppPluginStartDependencies>) {
public setup(core: CoreSetup<AppPluginStartDependencies, void>) {
core.application.register({
id: 'searchExplorer',
title: 'Search Explorer',

View file

@ -177,13 +177,18 @@ export { MountPoint, UnmountCallback, PublicUiSettingsParams } from './types';
/**
* Core services exposed to the `Plugin` setup lifecycle
*
* @typeParam TPluginsStart - the type of the consuming plugin's start dependencies. Should be the same
* as the consuming {@link Plugin}'s `TPluginsStart` type. Used by `getStartServices`.
* @typeParam TStart - the type of the consuming plugin's start contract. Should be the same as the
* consuming {@link Plugin}'s `TStart` type. Used by `getStartServices`.
*
* @public
*
* @internalRemarks We document the properties with \@link tags to improve
* navigation in the generated docs until there's a fix for
* https://github.com/Microsoft/web-build-tools/issues/1237
*/
export interface CoreSetup<TPluginsStart extends object = object> {
export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown> {
/** {@link ApplicationSetup} */
application: ApplicationSetup;
/**
@ -209,7 +214,7 @@ export interface CoreSetup<TPluginsStart extends object = object> {
getInjectedVar: (name: string, defaultValue?: any) => unknown;
};
/** {@link StartServicesAccessor} */
getStartServices: StartServicesAccessor<TPluginsStart>;
getStartServices: StartServicesAccessor<TPluginsStart, TStart>;
}
/**
@ -219,9 +224,10 @@ export interface CoreSetup<TPluginsStart extends object = object> {
*
* @public
*/
export type StartServicesAccessor<TPluginsStart extends object = object> = () => Promise<
[CoreStart, TPluginsStart]
>;
export type StartServicesAccessor<
TPluginsStart extends object = object,
TStart = unknown
> = () => Promise<[CoreStart, TPluginsStart, TStart]>;
/**
* Core services exposed to the `Plugin` start lifecycle
@ -274,7 +280,7 @@ export interface CoreStart {
* @public
* @deprecated
*/
export interface LegacyCoreSetup extends CoreSetup<any> {
export interface LegacyCoreSetup extends CoreSetup<any, any> {
/** @deprecated */
injectedMetadata: InjectedMetadataSetup;
}

View file

@ -57,7 +57,7 @@ export class LegacyPlatformService {
public readonly legacyId = Symbol();
private bootstrapModule?: BootstrapModule;
private targetDomElement?: HTMLElement;
private readonly startDependencies$ = new Subject<[LegacyCoreStart, object]>();
private readonly startDependencies$ = new Subject<[LegacyCoreStart, object, {}]>();
private readonly startDependencies = this.startDependencies$.pipe(first()).toPromise();
constructor(private readonly params: LegacyPlatformParams) {}
@ -129,7 +129,7 @@ export class LegacyPlatformService {
},
};
this.startDependencies$.next([legacyCore, plugins]);
this.startDependencies$.next([legacyCore, plugins, {}]);
// Inject parts of the new platform into parts of the legacy platform
// so that legacy APIs/modules can mimic their new platform counterparts

View file

@ -49,13 +49,22 @@ export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock';
export { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock';
export { scopedHistoryMock } from './application/scoped_history.mock';
function createCoreSetupMock({ basePath = '' } = {}) {
function createCoreSetupMock({
basePath = '',
pluginStartDeps = {},
pluginStartContract,
}: {
basePath?: string;
pluginStartDeps?: object;
pluginStartContract?: any;
} = {}) {
const mock = {
application: applicationServiceMock.createSetupContract(),
context: contextServiceMock.createSetupContract(),
fatalErrors: fatalErrorsServiceMock.createSetupContract(),
getStartServices: jest.fn<Promise<[ReturnType<typeof createCoreStartMock>, object]>, []>(() =>
Promise.resolve([createCoreStartMock({ basePath }), {}])
getStartServices: jest.fn<Promise<[ReturnType<typeof createCoreStartMock>, object, any]>, []>(
() =>
Promise.resolve([createCoreStartMock({ basePath }), pluginStartDeps, pluginStartContract])
),
http: httpServiceMock.createSetupContract({ basePath }),
notifications: notificationServiceMock.createSetupContract(),

View file

@ -109,6 +109,10 @@ describe('PluginWrapper', () => {
test("`start` resolves `startDependencies` Promise after plugin's start", async () => {
expect.assertions(2);
const pluginStartContract = {
someApi: () => 'foo',
};
let startDependenciesResolved = false;
mockPluginLoader.mockResolvedValueOnce(() => ({
setup: jest.fn(),
@ -116,6 +120,7 @@ describe('PluginWrapper', () => {
// Add small delay to ensure startDependencies is not resolved until after the plugin instance's start resolves.
await new Promise(resolve => setTimeout(resolve, 10));
expect(startDependenciesResolved).toBe(false);
return pluginStartContract;
},
}));
await plugin.load(addBasePath);
@ -127,7 +132,7 @@ describe('PluginWrapper', () => {
// called.
const startDependenciesCheck = plugin.startDependencies.then(res => {
startDependenciesResolved = true;
expect(res).toEqual([context, deps]);
expect(res).toEqual([context, deps, pluginStartContract]);
});
await plugin.start(context, deps);
await startDependenciesCheck;

View file

@ -35,7 +35,7 @@ export interface Plugin<
TPluginsSetup extends object = object,
TPluginsStart extends object = object
> {
setup(core: CoreSetup<TPluginsStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>;
setup(core: CoreSetup<TPluginsStart, TStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>;
start(core: CoreStart, plugins: TPluginsStart): TStart | Promise<TStart>;
stop?(): void;
}
@ -72,7 +72,7 @@ export class PluginWrapper<
private initializer?: PluginInitializer<TSetup, TStart, TPluginsSetup, TPluginsStart>;
private instance?: Plugin<TSetup, TStart, TPluginsSetup, TPluginsStart>;
private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart]>();
private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart, TStart]>();
public readonly startDependencies = this.startDependencies$.pipe(first()).toPromise();
constructor(
@ -105,7 +105,7 @@ export class PluginWrapper<
* @param plugins The dictionary where the key is the dependency name and the value
* is the contract returned by the dependency's `setup` function.
*/
public async setup(setupContext: CoreSetup<TPluginsStart>, plugins: TPluginsSetup) {
public async setup(setupContext: CoreSetup<TPluginsStart, TStart>, plugins: TPluginsSetup) {
this.instance = await this.createPluginInstance();
return await this.instance.setup(setupContext, plugins);
@ -125,7 +125,7 @@ export class PluginWrapper<
const startContract = await this.instance.start(startContext, plugins);
this.startDependencies$.next([startContext, plugins]);
this.startDependencies$.next([startContext, plugins, startContract]);
return startContract;
}

View file

@ -53,7 +53,7 @@ export interface PluginsServiceStart {
*/
export class PluginsService implements CoreService<PluginsServiceSetup, PluginsServiceStart> {
/** Plugin wrappers in topological order. */
private readonly plugins = new Map<PluginName, PluginWrapper<unknown, Record<string, unknown>>>();
private readonly plugins = new Map<PluginName, PluginWrapper<unknown, unknown>>();
private readonly pluginDependencies = new Map<PluginName, PluginName[]>();
private readonly satupPlugins: PluginName[] = [];

View file

@ -371,7 +371,7 @@ export interface CoreContext {
}
// @public
export interface CoreSetup<TPluginsStart extends object = object> {
export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown> {
// (undocumented)
application: ApplicationSetup;
// @deprecated (undocumented)
@ -379,7 +379,7 @@ export interface CoreSetup<TPluginsStart extends object = object> {
// (undocumented)
fatalErrors: FatalErrorsSetup;
// (undocumented)
getStartServices: StartServicesAccessor<TPluginsStart>;
getStartServices: StartServicesAccessor<TPluginsStart, TStart>;
// (undocumented)
http: HttpSetup;
// @deprecated
@ -807,7 +807,7 @@ export interface IUiSettingsClient {
}
// @public @deprecated
export interface LegacyCoreSetup extends CoreSetup<any> {
export interface LegacyCoreSetup extends CoreSetup<any, any> {
// Warning: (ae-forgotten-export) The symbol "InjectedMetadataSetup" needs to be exported by the entry point index.d.ts
//
// @deprecated (undocumented)
@ -907,7 +907,7 @@ export interface PackageInfo {
// @public
export interface Plugin<TSetup = void, TStart = void, TPluginsSetup extends object = object, TPluginsStart extends object = object> {
// (undocumented)
setup(core: CoreSetup<TPluginsStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>;
setup(core: CoreSetup<TPluginsStart, TStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>;
// (undocumented)
start(core: CoreStart, plugins: TPluginsStart): TStart | Promise<TStart>;
// (undocumented)
@ -1237,7 +1237,7 @@ export class SimpleSavedObject<T = unknown> {
}
// @public
export type StartServicesAccessor<TPluginsStart extends object = object> = () => Promise<[CoreStart, TPluginsStart]>;
export type StartServicesAccessor<TPluginsStart extends object = object, TStart = unknown> = () => Promise<[CoreStart, TPluginsStart, TStart]>;
// @public
export type StringValidation = StringValidationRegex | StringValidationRegexString;

View file

@ -333,9 +333,13 @@ export interface RequestHandlerContext {
/**
* Context passed to the plugins `setup` method.
*
* @typeParam TPluginsStart - the type of the consuming plugin's start dependencies. Should be the same
* as the consuming {@link Plugin}'s `TPluginsStart` type. Used by `getStartServices`.
* @typeParam TStart - the type of the consuming plugin's start contract. Should be the same as the
* consuming {@link Plugin}'s `TStart` type. Used by `getStartServices`.
* @public
*/
export interface CoreSetup<TPluginsStart extends object = object> {
export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown> {
/** {@link CapabilitiesSetup} */
capabilities: CapabilitiesSetup;
/** {@link ContextSetup} */
@ -353,7 +357,7 @@ export interface CoreSetup<TPluginsStart extends object = object> {
/** {@link MetricsServiceSetup} */
metrics: MetricsServiceSetup;
/** {@link StartServicesAccessor} */
getStartServices: StartServicesAccessor<TPluginsStart>;
getStartServices: StartServicesAccessor<TPluginsStart, TStart>;
}
/**
@ -364,9 +368,10 @@ export interface CoreSetup<TPluginsStart extends object = object> {
*
* @public
*/
export type StartServicesAccessor<TPluginsStart extends object = object> = () => Promise<
[CoreStart, TPluginsStart]
>;
export type StartServicesAccessor<
TPluginsStart extends object = object,
TStart = unknown
> = () => Promise<[CoreStart, TPluginsStart, TStart]>;
/**
* Context passed to the plugins `start` method.

View file

@ -312,7 +312,7 @@ export class LegacyService implements CoreService {
uuid: {
getInstanceUuid: setupDeps.core.uuid.getInstanceUuid,
},
getStartServices: () => Promise.resolve([coreStart, startDeps.plugins]),
getStartServices: () => Promise.resolve([coreStart, startDeps.plugins, {}]),
};
// eslint-disable-next-line @typescript-eslint/no-var-requires

View file

@ -96,7 +96,13 @@ function pluginInitializerContextMock<T>(config: T = {} as T) {
type CoreSetupMockType = MockedKeys<CoreSetup> & jest.Mocked<Pick<CoreSetup, 'getStartServices'>>;
function createCoreSetupMock() {
function createCoreSetupMock({
pluginStartDeps = {},
pluginStartContract,
}: {
pluginStartDeps?: object;
pluginStartContract?: any;
} = {}) {
const httpService = httpServiceMock.createSetupContract();
const httpMock: jest.Mocked<CoreSetup['http']> = {
createCookieSessionStorageFactory: httpService.createCookieSessionStorageFactory,
@ -131,8 +137,8 @@ function createCoreSetupMock() {
uuid: uuidServiceMock.createSetupContract(),
metrics: metricsServiceMock.createSetupContract(),
getStartServices: jest
.fn<Promise<[ReturnType<typeof createCoreStartMock>, object]>, []>()
.mockResolvedValue([createCoreStartMock(), {}]),
.fn<Promise<[ReturnType<typeof createCoreStartMock>, object, any]>, []>()
.mockResolvedValue([createCoreStartMock(), pluginStartDeps, pluginStartContract]),
};
return mock;

View file

@ -107,7 +107,7 @@ describe('PluginsService', () => {
});
it("properly resolves `getStartServices` in plugin's lifecycle", async () => {
expect.assertions(5);
expect.assertions(6);
const pluginPath = 'plugin-path';
@ -125,20 +125,25 @@ describe('PluginsService', () => {
let contextFromStart: any = null;
let contextFromStartService: any = null;
const pluginStartContract = {
someApi: () => 'foo',
};
const pluginInitializer = () =>
({
setup: async (coreSetup, deps) => {
coreSetup.getStartServices().then(([core, plugins]) => {
coreSetup.getStartServices().then(([core, plugins, pluginStart]) => {
startDependenciesResolved = true;
contextFromStartService = { core, plugins };
contextFromStartService = { core, plugins, pluginStart };
});
},
start: async (core, plugins) => {
contextFromStart = { core, plugins };
await new Promise(resolve => setTimeout(resolve, 10));
expect(startDependenciesResolved).toBe(false);
return pluginStartContract;
},
} as Plugin);
} as Plugin<void, typeof pluginStartContract, {}, {}>);
jest.doMock(
join(pluginPath, 'server'),
@ -163,5 +168,6 @@ describe('PluginsService', () => {
expect(startDependenciesResolved).toBe(true);
expect(contextFromStart!.core).toEqual(contextFromStartService!.core);
expect(contextFromStart!.plugins).toEqual(contextFromStartService!.plugins);
expect(contextFromStartService!.pluginStart).toEqual(pluginStartContract);
});
});

View file

@ -250,6 +250,9 @@ test("`start` resolves `startDependencies` Promise after plugin's start", async
});
const startContext = { any: 'thing' } as any;
const pluginDeps = { someDep: 'value' };
const pluginStartContract = {
someApi: () => 'foo',
};
let startDependenciesResolved = false;
@ -259,6 +262,7 @@ test("`start` resolves `startDependencies` Promise after plugin's start", async
// delay to ensure startDependencies is not resolved until after the plugin instance's start resolves.
await new Promise(resolve => setTimeout(resolve, 10));
expect(startDependenciesResolved).toBe(false);
return pluginStartContract;
},
};
mockPluginInitializer.mockReturnValue(mockPluginInstance);
@ -267,7 +271,7 @@ test("`start` resolves `startDependencies` Promise after plugin's start", async
const startDependenciesCheck = plugin.startDependencies.then(resolvedStartDeps => {
startDependenciesResolved = true;
expect(resolvedStartDeps).toEqual([startContext, pluginDeps]);
expect(resolvedStartDeps).toEqual([startContext, pluginDeps, pluginStartContract]);
});
await plugin.start(startContext, pluginDeps);

View file

@ -61,7 +61,7 @@ export class PluginWrapper<
private instance?: Plugin<TSetup, TStart, TPluginsSetup, TPluginsStart>;
private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart]>();
private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart, TStart]>();
public readonly startDependencies = this.startDependencies$.pipe(first()).toPromise();
constructor(
@ -115,7 +115,7 @@ export class PluginWrapper<
this.log.debug('Starting plugin');
const startContract = await this.instance.start(startContext, plugins);
this.startDependencies$.next([startContext, plugins]);
this.startDependencies$.next([startContext, plugins, startContract]);
return startContract;
}

View file

@ -622,7 +622,7 @@ export interface ContextSetup {
export type CoreId = symbol;
// @public
export interface CoreSetup<TPluginsStart extends object = object> {
export interface CoreSetup<TPluginsStart extends object = object, TStart = unknown> {
// (undocumented)
capabilities: CapabilitiesSetup;
// (undocumented)
@ -630,7 +630,7 @@ export interface CoreSetup<TPluginsStart extends object = object> {
// (undocumented)
elasticsearch: ElasticsearchServiceSetup;
// (undocumented)
getStartServices: StartServicesAccessor<TPluginsStart>;
getStartServices: StartServicesAccessor<TPluginsStart, TStart>;
// (undocumented)
http: HttpServiceSetup;
// (undocumented)
@ -2270,7 +2270,7 @@ export type SharedGlobalConfig = RecursiveReadonly_2<{
}>;
// @public
export type StartServicesAccessor<TPluginsStart extends object = object> = () => Promise<[CoreStart, TPluginsStart]>;
export type StartServicesAccessor<TPluginsStart extends object = object, TStart = unknown> = () => Promise<[CoreStart, TPluginsStart, TStart]>;
// @public
export type StringValidation = StringValidationRegex | StringValidationRegexString;

View file

@ -24,7 +24,7 @@ import { VisualizationsSetup, VisualizationsStart } from '../../visualizations/p
import { createInputControlVisFn } from './input_control_fn';
import { createInputControlVisTypeDefinition } from './input_control_vis_type';
type InputControlVisCoreSetup = CoreSetup<InputControlVisPluginStartDependencies>;
type InputControlVisCoreSetup = CoreSetup<InputControlVisPluginStartDependencies, void>;
export interface InputControlVisDependencies {
core: InputControlVisCoreSetup;
@ -46,7 +46,7 @@ export interface InputControlVisPluginStartDependencies {
}
/** @internal */
export class InputControlVisPlugin implements Plugin<Promise<void>, void> {
export class InputControlVisPlugin implements Plugin<void, void> {
constructor(public initializerContext: PluginInitializerContext) {}
public async setup(

View file

@ -91,7 +91,7 @@ export class DiscoverPlugin implements Plugin<void, void> {
public initializeInnerAngular?: () => void;
public initializeServices?: () => Promise<{ core: CoreStart; plugins: DiscoverStartPlugins }>;
setup(core: CoreSetup<DiscoverStartPlugins>, plugins: DiscoverSetupPlugins) {
setup(core: CoreSetup<DiscoverStartPlugins, void>, plugins: DiscoverSetupPlugins) {
const { appMounted, appUnMounted, stop: stopUrlTracker } = createKbnUrlTracker({
baseUrl: core.http.basePath.prepend('/app/kibana'),
defaultSubUrl: '#/discover',

View file

@ -35,7 +35,7 @@ import { getTimelionVisualizationConfig } from './timelion_vis_fn';
import { getTimelionVisDefinition } from './timelion_vis_type';
import { setIndexPatterns, setSavedObjectsClient } from './helpers/plugin_services';
type TimelionVisCoreSetup = CoreSetup<TimelionVisSetupDependencies>;
type TimelionVisCoreSetup = CoreSetup<TimelionVisSetupDependencies, void>;
/** @internal */
export interface TimelionVisDependencies extends Partial<CoreStart> {

View file

@ -62,10 +62,10 @@ export interface VisTypeVislibPluginStartDependencies {
data: DataPublicPluginStart;
}
type VisTypeVislibCoreSetup = CoreSetup<VisTypeVislibPluginStartDependencies>;
type VisTypeVislibCoreSetup = CoreSetup<VisTypeVislibPluginStartDependencies, void>;
/** @internal */
export class VisTypeVislibPlugin implements Plugin<Promise<void>, void> {
export class VisTypeVislibPlugin implements Plugin<void, void> {
constructor(public initializerContext: PluginInitializerContext) {}
public async setup(

View file

@ -47,10 +47,10 @@ export interface VisTypeXyPluginStartDependencies {
visualizations: VisualizationsStart;
}
type VisTypeXyCoreSetup = CoreSetup<VisTypeXyPluginStartDependencies>;
type VisTypeXyCoreSetup = CoreSetup<VisTypeXyPluginStartDependencies, void>;
/** @internal */
export class VisTypeXyPlugin implements Plugin<Promise<void>, void> {
export class VisTypeXyPlugin implements Plugin<void, void> {
constructor(public initializerContext: PluginInitializerContext) {}
public async setup(

View file

@ -50,7 +50,9 @@ export interface HomePluginSetupDependencies {
kibanaLegacy: KibanaLegacySetup;
}
export class HomePublicPlugin implements Plugin<HomePublicPluginSetup, void> {
export class HomePublicPlugin
implements
Plugin<HomePublicPluginSetup, void, HomePluginSetupDependencies, HomePluginStartDependencies> {
private readonly featuresCatalogueRegistry = new FeatureCatalogueRegistry();
private readonly environmentService = new EnvironmentService();
private readonly tutorialService = new TutorialService();

View file

@ -175,7 +175,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
const usageCollection = plugins.usageCollection;
if (usageCollection) {
core.getStartServices().then(async ([coreStart, startPlugins]: [CoreStart, any]) => {
core.getStartServices().then(async ([, startPlugins]: [CoreStart, any, any]) => {
registerActionsUsageCollector(usageCollection, startPlugins.taskManager);
initializeActionsTelemetry(

View file

@ -143,7 +143,7 @@ export class AlertingPlugin {
const usageCollection = plugins.usageCollection;
if (usageCollection) {
core.getStartServices().then(async ([coreStart, startPlugins]: [CoreStart, any]) => {
core.getStartServices().then(async ([, startPlugins]: [CoreStart, any, any]) => {
registerAlertsUsageCollector(usageCollection, startPlugins.taskManager);
initializeAlertingTelemetry(

View file

@ -32,7 +32,9 @@ export interface IngestManagerStartDeps {
data: DataPublicPluginStart;
}
export class IngestManagerPlugin implements Plugin {
export class IngestManagerPlugin
implements
Plugin<IngestManagerSetup, IngestManagerStart, IngestManagerSetupDeps, IngestManagerStartDeps> {
private config: IngestManagerConfigType;
constructor(private readonly initializerContext: PluginInitializerContext) {
@ -50,7 +52,8 @@ export class IngestManagerPlugin implements Plugin {
async mount(params: AppMountParameters) {
const [coreStart, startDeps] = (await core.getStartServices()) as [
CoreStart,
IngestManagerStartDeps
IngestManagerStartDeps,
IngestManagerStart
];
const { renderApp } = await import('./applications/ingest_manager');
return renderApp(coreStart, params, deps, startDeps, config);

View file

@ -6,8 +6,19 @@
import { PluginInitializer } from 'kibana/public';
import './index.scss';
import { MlPlugin, MlPluginSetup, MlPluginStart } from './plugin';
import {
MlPlugin,
MlPluginSetup,
MlPluginStart,
MlSetupDependencies,
MlStartDependencies,
} from './plugin';
export const plugin: PluginInitializer<MlPluginSetup, MlPluginStart> = () => new MlPlugin();
export const plugin: PluginInitializer<
MlPluginSetup,
MlPluginStart,
MlSetupDependencies,
MlStartDependencies
> = () => new MlPlugin();
export { MlPluginSetup, MlPluginStart };

View file

@ -31,7 +31,7 @@ export interface MlSetupDependencies {
}
export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
setup(core: CoreSetup<MlStartDependencies>, pluginsSetup: MlSetupDependencies) {
setup(core: CoreSetup<MlStartDependencies, MlPluginStart>, pluginsSetup: MlSetupDependencies) {
core.application.register({
id: PLUGIN_ID,
title: i18n.translate('xpack.ml.plugin.title', {

View file

@ -224,7 +224,7 @@ export class Plugin {
this.monitoringCore = this.getLegacyShim(
config,
legacyConfig,
core.getStartServices as () => Promise<[CoreStart, PluginsStart]>,
core.getStartServices as () => Promise<[CoreStart, PluginsStart, {}]>,
this.licenseService,
this.cluster
);
@ -293,7 +293,7 @@ export class Plugin {
getLegacyShim(
config: MonitoringConfig,
legacyConfig: any,
getCoreServices: () => Promise<[CoreStart, PluginsStart]>,
getCoreServices: () => Promise<[CoreStart, PluginsStart, {}]>,
licenseService: MonitoringLicenseService,
cluster: ICustomClusterClient
): MonitoringCore {

View file

@ -38,7 +38,7 @@ describe('accountManagementApp', () => {
it('properly sets breadcrumbs and renders application', async () => {
const coreSetupMock = coreMock.createSetup();
const coreStartMock = coreMock.createStart();
coreSetupMock.getStartServices.mockResolvedValue([coreStartMock, {}]);
coreSetupMock.getStartServices.mockResolvedValue([coreStartMock, {}, {}]);
const authcMock = securityMock.createSetup().authc;
const containerMock = document.createElement('div');

View file

@ -35,7 +35,7 @@ describe('loggedOutApp', () => {
it('properly renders application', async () => {
const coreSetupMock = coreMock.createSetup();
const coreStartMock = coreMock.createStart();
coreSetupMock.getStartServices.mockResolvedValue([coreStartMock, {}]);
coreSetupMock.getStartServices.mockResolvedValue([coreStartMock, {}, {}]);
const containerMock = document.createElement('div');

View file

@ -38,7 +38,7 @@ describe('loginApp', () => {
it('properly renders application', async () => {
const coreSetupMock = coreMock.createSetup();
const coreStartMock = coreMock.createStart();
coreSetupMock.getStartServices.mockResolvedValue([coreStartMock, {}]);
coreSetupMock.getStartServices.mockResolvedValue([coreStartMock, {}, {}]);
const containerMock = document.createElement('div');
loginApp.create({

View file

@ -37,7 +37,7 @@ describe('overwrittenSessionApp', () => {
it('properly sets breadcrumbs and renders application', async () => {
const coreSetupMock = coreMock.createSetup();
const coreStartMock = coreMock.createStart();
coreSetupMock.getStartServices.mockResolvedValue([coreStartMock, {}]);
coreSetupMock.getStartServices.mockResolvedValue([coreStartMock, {}, {}]);
const authcMock = securityMock.createSetup().authc;
const containerMock = document.createElement('div');

View file

@ -6,13 +6,22 @@
import './index.scss';
import { PluginInitializer, PluginInitializerContext } from 'src/core/public';
import { SecurityPlugin, SecurityPluginSetup, SecurityPluginStart } from './plugin';
import {
SecurityPlugin,
SecurityPluginSetup,
SecurityPluginStart,
PluginSetupDependencies,
PluginStartDependencies,
} from './plugin';
export { SecurityPluginSetup, SecurityPluginStart };
export { SessionInfo } from './types';
export { AuthenticatedUser } from '../common/model';
export { SecurityLicense, SecurityLicenseFeatures } from '../common/licensing';
export const plugin: PluginInitializer<SecurityPluginSetup, SecurityPluginStart> = (
initializerContext: PluginInitializerContext
) => new SecurityPlugin(initializerContext);
export const plugin: PluginInitializer<
SecurityPluginSetup,
SecurityPluginStart,
PluginSetupDependencies,
PluginStartDependencies
> = (initializerContext: PluginInitializerContext) => new SecurityPlugin(initializerContext);

View file

@ -51,7 +51,7 @@ async function mountApp(basePath: string, spaceId?: string) {
.create({
spacesManager,
securityLicense,
getStartServices: async () => [coreStart, pluginsStart as PluginsStart],
getStartServices: async () => [coreStart, pluginsStart as PluginsStart, {}],
})
.mount({ basePath, element: container, setBreadcrumbs });

View file

@ -103,6 +103,7 @@ const setup = (space: Space) => {
coreSetup.getStartServices.mockResolvedValue([
coreMock.createStart(),
{ features: featuresStart },
{},
]);
const spacesService = spacesServiceMock.createSetupContract();

View file

@ -5,6 +5,15 @@
*/
import { PluginInitializer } from 'kibana/public';
import { ResolverTestPlugin } from './plugin';
import {
ResolverTestPlugin,
ResolverTestPluginSetupDependencies,
ResolverTestPluginStartDependencies,
} from './plugin';
export const plugin: PluginInitializer<void, void> = () => new ResolverTestPlugin();
export const plugin: PluginInitializer<
void,
void,
ResolverTestPluginSetupDependencies,
ResolverTestPluginStartDependencies
> = () => new ResolverTestPlugin();