Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getStartServices API #50231

Merged
merged 3 commits into from
Dec 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/development/core/public/kibana-plugin-public.app.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ export interface App extends AppBase
| Property | Type | Description |
| --- | --- | --- |
| [chromeless](./kibana-plugin-public.app.chromeless.md) | <code>boolean</code> | Hide the UI chrome when the application is mounted. Defaults to <code>false</code>. Takes precedence over chrome service visibility settings. |
| [mount](./kibana-plugin-public.app.mount.md) | <code>(context: AppMountContext, params: AppMountParameters) =&gt; AppUnmount &#124; Promise&lt;AppUnmount&gt;</code> | A mount function called when the user navigates to this app's route. |
| [mount](./kibana-plugin-public.app.mount.md) | <code>AppMount &#124; AppMountDeprecated</code> | A mount function called when the user navigates to this app's route. May have signature of [AppMount](./kibana-plugin-public.appmount.md) or [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md)<!-- -->. |

Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@

## App.mount property

A mount function called when the user navigates to this app's route.
A mount function called when the user navigates to this app's route. May have signature of [AppMount](./kibana-plugin-public.appmount.md) or [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md)<!-- -->.

<b>Signature:</b>

```typescript
mount: (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise<AppUnmount>;
mount: AppMount | AppMountDeprecated;
```

## Remarks

When function has two arguments, it will be called with a [context](./kibana-plugin-public.appmountcontext.md) as the first argument. This behavior is \*\*deprecated\*\*, and consumers should instead use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md)<!-- -->.

Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ export interface ApplicationSetup
| Method | Description |
| --- | --- |
| [register(app)](./kibana-plugin-public.applicationsetup.register.md) | Register an mountable application to the system. |
| [registerMountContext(contextName, provider)](./kibana-plugin-public.applicationsetup.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. |
| [registerMountContext(contextName, provider)](./kibana-plugin-public.applicationsetup.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md)<!-- -->. |

Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,24 @@

## ApplicationSetup.registerMountContext() method

Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context.
> Warning: This API is now obsolete.
>
>

Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md)<!-- -->.

<b>Signature:</b>

```typescript
registerMountContext<T extends keyof AppMountContext>(contextName: T, provider: IContextProvider<App['mount'], T>): void;
registerMountContext<T extends keyof AppMountContext>(contextName: T, provider: IContextProvider<AppMountDeprecated, T>): void;
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| contextName | <code>T</code> | The key of [AppMountContext](./kibana-plugin-public.appmountcontext.md) this provider's return value should be attached to. |
| provider | <code>IContextProvider&lt;App['mount'], T&gt;</code> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function |
| provider | <code>IContextProvider&lt;AppMountDeprecated, T&gt;</code> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function |

<b>Returns:</b>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ export interface ApplicationStart
| --- | --- |
| [getUrlForApp(appId, options)](./kibana-plugin-public.applicationstart.geturlforapp.md) | Returns a relative URL to a given app, including the global base path. |
| [navigateToApp(appId, options)](./kibana-plugin-public.applicationstart.navigatetoapp.md) | Navigiate to a given app |
| [registerMountContext(contextName, provider)](./kibana-plugin-public.applicationstart.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. |
| [registerMountContext(contextName, provider)](./kibana-plugin-public.applicationstart.registermountcontext.md) | Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md)<!-- -->. |

Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,24 @@

## ApplicationStart.registerMountContext() method

Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context.
> Warning: This API is now obsolete.
>
>

Register a context provider for application mounting. Will only be available to applications that depend on the plugin that registered this context. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md)<!-- -->.

<b>Signature:</b>

```typescript
registerMountContext<T extends keyof AppMountContext>(contextName: T, provider: IContextProvider<App['mount'], T>): void;
registerMountContext<T extends keyof AppMountContext>(contextName: T, provider: IContextProvider<AppMountDeprecated, T>): void;
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| contextName | <code>T</code> | The key of [AppMountContext](./kibana-plugin-public.appmountcontext.md) this provider's return value should be attached to. |
| provider | <code>IContextProvider&lt;App['mount'], T&gt;</code> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function |
| provider | <code>IContextProvider&lt;AppMountDeprecated, T&gt;</code> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function |

<b>Returns:</b>

Expand Down
13 changes: 13 additions & 0 deletions docs/development/core/public/kibana-plugin-public.appmount.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [AppMount](./kibana-plugin-public.appmount.md)

## AppMount type

A mount function called when the user navigates to this app's route.

<b>Signature:</b>

```typescript
export declare type AppMount = (params: AppMountParameters) => AppUnmount | Promise<AppUnmount>;
```
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

## AppMountContext interface

The context object received when applications are mounted to the DOM.
> Warning: This API is now obsolete.
>
>

The context object received when applications are mounted to the DOM. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md)<!-- -->.

<b>Signature:</b>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md)

## AppMountDeprecated type

> Warning: This API is now obsolete.
>
>

A mount function called when the user navigates to this app's route.

<b>Signature:</b>

```typescript
export declare type AppMountDeprecated = (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise<AppUnmount>;
```

## Remarks

When function has two arguments, it will be called with a [context](./kibana-plugin-public.appmountcontext.md) as the first argument. This behavior is \*\*deprecated\*\*, and consumers should instead use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md)<!-- -->.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

## CoreSetup.context property

> Warning: This API is now obsolete.
>
>

[ContextSetup](./kibana-plugin-public.contextsetup.md)

<b>Signature:</b>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [CoreSetup](./kibana-plugin-public.coresetup.md) &gt; [getStartServices](./kibana-plugin-public.coresetup.getstartservices.md)

## CoreSetup.getStartServices() method

Allows plugins to get access to APIs available in start inside async handlers, such as [App.mount](./kibana-plugin-public.app.mount.md)<!-- -->. Promise will not resolve until Core and plugin dependencies have completed `start`<!-- -->.

<b>Signature:</b>

```typescript
getStartServices(): Promise<[CoreStart, TPluginsStart]>;
```
<b>Returns:</b>

`Promise<[CoreStart, TPluginsStart]>`

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Core services exposed to the `Plugin` setup lifecycle
<b>Signature:</b>

```typescript
export interface CoreSetup
export interface CoreSetup<TPluginsStart extends object = object>
```

## Properties
Expand All @@ -24,3 +24,9 @@ export interface CoreSetup
| [notifications](./kibana-plugin-public.coresetup.notifications.md) | <code>NotificationsSetup</code> | [NotificationsSetup](./kibana-plugin-public.notificationssetup.md) |
| [uiSettings](./kibana-plugin-public.coresetup.uisettings.md) | <code>IUiSettingsClient</code> | [IUiSettingsClient](./kibana-plugin-public.iuisettingsclient.md) |

## Methods

| Method | Description |
| --- | --- |
| [getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md) | Allows plugins to get access to APIs available in start inside async handlers, such as [App.mount](./kibana-plugin-public.app.mount.md)<!-- -->. Promise will not resolve until Core and plugin dependencies have completed <code>start</code>. |

Original file line number Diff line number Diff line change
Expand Up @@ -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
export interface LegacyCoreSetup extends CoreSetup<any>
```

## Properties
Expand Down
4 changes: 3 additions & 1 deletion docs/development/core/public/kibana-plugin-public.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [AppBase](./kibana-plugin-public.appbase.md) | |
| [ApplicationSetup](./kibana-plugin-public.applicationsetup.md) | |
| [ApplicationStart](./kibana-plugin-public.applicationstart.md) | |
| [AppMountContext](./kibana-plugin-public.appmountcontext.md) | The context object received when applications are mounted to the DOM. |
| [AppMountContext](./kibana-plugin-public.appmountcontext.md) | The context object received when applications are mounted to the DOM. Deprecated, use [CoreSetup.getStartServices()](./kibana-plugin-public.coresetup.getstartservices.md)<!-- -->. |
| [AppMountParameters](./kibana-plugin-public.appmountparameters.md) | |
| [Capabilities](./kibana-plugin-public.capabilities.md) | The read-only set of capabilities available for the current UI session. Capabilities are simple key-value pairs of (string, boolean), where the string denotes the capability ID, and the boolean is a flag indicating if the capability is enabled or disabled. |
| [ChromeBadge](./kibana-plugin-public.chromebadge.md) | |
Expand Down Expand Up @@ -98,6 +98,8 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->

| Type Alias | Description |
| --- | --- |
| [AppMount](./kibana-plugin-public.appmount.md) | A mount function called when the user navigates to this app's route. |
| [AppMountDeprecated](./kibana-plugin-public.appmountdeprecated.md) | A mount function called when the user navigates to this app's route. |
| [AppUnmount](./kibana-plugin-public.appunmount.md) | A function called when an application should be unmounted from the page. This function should be synchronous. |
| [ChromeBreadcrumb](./kibana-plugin-public.chromebreadcrumb.md) | |
| [ChromeHelpExtensionMenuCustomLink](./kibana-plugin-public.chromehelpextensionmenucustomlink.md) | |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
<b>Signature:</b>

```typescript
setup(core: CoreSetup, plugins: TPluginsSetup): TSetup | Promise<TSetup>;
setup(core: CoreSetup<TPluginsStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>;
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| core | <code>CoreSetup</code> | |
| core | <code>CoreSetup&lt;TPluginsStart&gt;</code> | |
| plugins | <code>TPluginsSetup</code> | |

<b>Returns:</b>
Expand Down
36 changes: 25 additions & 11 deletions src/core/public/application/application_service.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ describe('#setup()', () => {
const service = new ApplicationService();
const context = contextServiceMock.createSetupContract();
const setup = service.setup({ context });
setup.register(Symbol(), { id: 'app1' } as any);
setup.register(Symbol(), { id: 'app1', mount: jest.fn() } as any);
expect(() =>
setup.register(Symbol(), { id: 'app1' } as any)
setup.register(Symbol(), { id: 'app1', mount: jest.fn() } as any)
).toThrowErrorMatchingInlineSnapshot(
`"An application is already registered with the id \\"app1\\""`
);
Expand All @@ -51,6 +51,18 @@ describe('#setup()', () => {
setup.register(Symbol(), { id: 'app1' } as any)
).toThrowErrorMatchingInlineSnapshot(`"Applications cannot be registered after \\"setup\\""`);
});

it('logs a warning when registering a deprecated app mount', async () => {
const consoleWarnSpy = jest.spyOn(console, 'warn');
const service = new ApplicationService();
const context = contextServiceMock.createSetupContract();
const setup = service.setup({ context });
setup.register(Symbol(), { id: 'app1', mount: (ctx: any, params: any) => {} } as any);
expect(consoleWarnSpy).toHaveBeenCalledWith(
`App [app1] is using deprecated mount context. Use core.getStartServices() instead.`
);
consoleWarnSpy.mockRestore();
});
});

describe('registerLegacyApp', () => {
Expand Down Expand Up @@ -100,20 +112,21 @@ describe('#start()', () => {
const service = new ApplicationService();
const context = contextServiceMock.createSetupContract();
const setup = service.setup({ context });
setup.register(Symbol(), { id: 'app1' } as any);
setup.register(Symbol(), { id: 'app1', mount: jest.fn() } as any);
setup.registerLegacyApp({ id: 'app2' } as any);

const http = httpServiceMock.createStartContract();
const injectedMetadata = injectedMetadataServiceMock.createStartContract();
const startContract = await service.start({ http, injectedMetadata });

expect(startContract.availableApps).toMatchInlineSnapshot(`
Map {
"app1" => Object {
"id": "app1",
},
}
`);
Map {
"app1" => Object {
"id": "app1",
"mount": [MockFunction],
},
}
`);
expect(startContract.availableLegacyApps).toMatchInlineSnapshot(`
Map {
"app2" => Object {
Expand All @@ -127,14 +140,15 @@ describe('#start()', () => {
const service = new ApplicationService();
const context = contextServiceMock.createSetupContract();
const setup = service.setup({ context });
setup.register(Symbol(), { id: 'app1' } as any);
const app1 = { id: 'app1', mount: jest.fn() };
setup.register(Symbol(), app1 as any);

const http = httpServiceMock.createStartContract();
const injectedMetadata = injectedMetadataServiceMock.createStartContract();
await service.start({ http, injectedMetadata });

expect(MockCapabilitiesService.start).toHaveBeenCalledWith({
apps: new Map([['app1', { id: 'app1' }]]),
apps: new Map([['app1', app1]]),
legacyApps: new Map(),
http,
});
Expand Down
35 changes: 26 additions & 9 deletions src/core/public/application/application_service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ import { ContextSetup, IContextContainer } from '../context';
import {
App,
LegacyApp,
AppMounter,
AppMount,
AppMountDeprecated,
InternalApplicationSetup,
InternalApplicationStart,
} from './types';
Expand All @@ -50,7 +51,7 @@ interface StartDeps {

interface AppBox {
app: App;
mount: AppMounter;
mount: AppMount;
}

/**
Expand All @@ -61,7 +62,7 @@ export class ApplicationService {
private readonly apps$ = new BehaviorSubject<ReadonlyMap<string, AppBox>>(new Map());
private readonly legacyApps$ = new BehaviorSubject<ReadonlyMap<string, LegacyApp>>(new Map());
private readonly capabilities = new CapabilitiesService();
private mountContext?: IContextContainer<App['mount']>;
private mountContext?: IContextContainer<AppMountDeprecated>;

public setup({ context }: SetupDeps): InternalApplicationSetup {
this.mountContext = context.createContextContainer();
Expand All @@ -75,10 +76,21 @@ export class ApplicationService {
throw new Error(`Applications cannot be registered after "setup"`);
}

const appBox: AppBox = {
app,
mount: this.mountContext!.createHandler(plugin, app.mount),
};
let appBox: AppBox;
if (isAppMountDeprecated(app.mount)) {
// eslint-disable-next-line no-console
console.warn(
`App [${app.id}] is using deprecated mount context. Use core.getStartServices() instead.`
);

appBox = {
app,
mount: this.mountContext!.createHandler(plugin, app.mount),
};
} else {
appBox = { app, mount: app.mount };
}

this.apps$.next(new Map([...this.apps$.value.entries(), [app.id, appBox]]));
},
registerLegacyApp: (app: LegacyApp) => {
Expand Down Expand Up @@ -146,15 +158,15 @@ export class ApplicationService {
}

// Filter only available apps and map to just the mount function.
const appMounters = new Map<string, AppMounter>(
const appMounts = new Map<string, AppMount>(
[...this.apps$.value]
.filter(([id]) => availableApps.has(id))
.map(([id, { mount }]) => [id, mount])
);

return (
<AppRouter
apps={appMounters}
apps={appMounts}
legacyApps={availableLegacyApps}
basePath={http.basePath}
currentAppId$={currentAppId$}
Expand All @@ -173,3 +185,8 @@ const appPath = (appId: string, { path }: { path?: string } = {}): string =>
path
? `/app/${appId}/${path.replace(/^\//, '')}` // Remove preceding slash from path if present
: `/app/${appId}`;

function isAppMountDeprecated(mount: (...args: any[]) => any): mount is AppMountDeprecated {
// Mount functions with two arguments are assumed to expect deprecated `context` object.
return mount.length === 2;
}
Loading