mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
parent
b184978f1f
commit
12153e5733
39 changed files with 388 additions and 94 deletions
|
@ -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) => AppUnmount | Promise<AppUnmount></code> | A mount function called when the user navigates to this app's route. |
|
||||
| [mount](./kibana-plugin-public.app.mount.md) | <code>AppMount | 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)<!-- -->. |
|
||||
|
||||
|
|
|
@ -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)<!-- -->.
|
||||
|
||||
|
|
|
@ -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)<!-- -->. |
|
||||
|
||||
|
|
|
@ -4,12 +4,16 @@
|
|||
|
||||
## 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
|
||||
|
@ -17,7 +21,7 @@ registerMountContext<T extends keyof AppMountContext>(contextName: T, provider:
|
|||
| 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<App['mount'], T></code> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function |
|
||||
| provider | <code>IContextProvider<AppMountDeprecated, T></code> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
|
|
@ -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)<!-- -->. |
|
||||
|
||||
|
|
|
@ -4,12 +4,16 @@
|
|||
|
||||
## 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
|
||||
|
@ -17,7 +21,7 @@ registerMountContext<T extends keyof AppMountContext>(contextName: T, provider:
|
|||
| 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<App['mount'], T></code> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function |
|
||||
| provider | <code>IContextProvider<AppMountDeprecated, T></code> | A [IContextProvider](./kibana-plugin-public.icontextprovider.md) function |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [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>;
|
||||
```
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [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)<!-- -->.
|
||||
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
## CoreSetup.context property
|
||||
|
||||
> Warning: This API is now obsolete.
|
||||
>
|
||||
>
|
||||
|
||||
[ContextSetup](./kibana-plugin-public.contextsetup.md)
|
||||
|
||||
<b>Signature:</b>
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [CoreSetup](./kibana-plugin-public.coresetup.md) > [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]>`
|
||||
|
|
@ -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
|
||||
|
@ -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>. |
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) | |
|
||||
|
@ -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) | |
|
||||
|
|
|
@ -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<TPluginsStart></code> | |
|
||||
| plugins | <code>TPluginsSetup</code> | |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
|
|
@ -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\\""`
|
||||
);
|
||||
|
@ -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', () => {
|
||||
|
@ -100,7 +112,7 @@ 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();
|
||||
|
@ -108,12 +120,13 @@ describe('#start()', () => {
|
|||
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 {
|
||||
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -29,7 +29,8 @@ import { ContextSetup, IContextContainer } from '../context';
|
|||
import {
|
||||
App,
|
||||
LegacyApp,
|
||||
AppMounter,
|
||||
AppMount,
|
||||
AppMountDeprecated,
|
||||
InternalApplicationSetup,
|
||||
InternalApplicationStart,
|
||||
} from './types';
|
||||
|
@ -50,7 +51,7 @@ interface StartDeps {
|
|||
|
||||
interface AppBox {
|
||||
app: App;
|
||||
mount: AppMounter;
|
||||
mount: AppMount;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
|
@ -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) => {
|
||||
|
@ -146,7 +158,7 @@ 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])
|
||||
|
@ -154,7 +166,7 @@ export class ApplicationService {
|
|||
|
||||
return (
|
||||
<AppRouter
|
||||
apps={appMounters}
|
||||
apps={appMounts}
|
||||
legacyApps={availableLegacyApps}
|
||||
basePath={http.basePath}
|
||||
currentAppId$={currentAppId$}
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ export { Capabilities } from './capabilities';
|
|||
export {
|
||||
App,
|
||||
AppBase,
|
||||
AppMount,
|
||||
AppMountDeprecated,
|
||||
AppUnmount,
|
||||
AppMountContext,
|
||||
AppMountParameters,
|
||||
|
|
|
@ -24,7 +24,7 @@ import { BehaviorSubject } from 'rxjs';
|
|||
|
||||
import { I18nProvider } from '@kbn/i18n/react';
|
||||
|
||||
import { AppMounter, LegacyApp, AppMountParameters } from '../types';
|
||||
import { AppMount, LegacyApp, AppMountParameters } from '../types';
|
||||
import { httpServiceMock } from '../../http/http_service.mock';
|
||||
import { AppRouter, AppNotFound } from '../ui';
|
||||
|
||||
|
@ -35,7 +35,7 @@ const createMountHandler = (htmlString: string) =>
|
|||
});
|
||||
|
||||
describe('AppContainer', () => {
|
||||
let apps: Map<string, jest.Mock<ReturnType<AppMounter>, Parameters<AppMounter>>>;
|
||||
let apps: Map<string, jest.Mock<ReturnType<AppMount>, Parameters<AppMount>>>;
|
||||
let legacyApps: Map<string, LegacyApp>;
|
||||
let history: History;
|
||||
let router: ReactWrapper;
|
||||
|
|
|
@ -75,12 +75,14 @@ export interface AppBase {
|
|||
*/
|
||||
export interface App extends AppBase {
|
||||
/**
|
||||
* A mount function called when the user navigates to this app's route.
|
||||
* @param context The mount context for this app.
|
||||
* @param targetDomElement An HTMLElement to mount the application onto.
|
||||
* @returns An unmounting function that will be called to unmount the application.
|
||||
* A mount function called when the user navigates to this app's route. May have signature of {@link AppMount} or
|
||||
* {@link AppMountDeprecated}.
|
||||
*
|
||||
* @remarks
|
||||
* When function has two arguments, it will be called with a {@link AppMountContext | context} as the first argument.
|
||||
* This behavior is **deprecated**, and consumers should instead use {@link CoreSetup.getStartServices}.
|
||||
*/
|
||||
mount: (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise<AppUnmount>;
|
||||
mount: AppMount | AppMountDeprecated;
|
||||
|
||||
/**
|
||||
* Hide the UI chrome when the application is mounted. Defaults to `false`.
|
||||
|
@ -97,7 +99,39 @@ export interface LegacyApp extends AppBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* The context object received when applications are mounted to the DOM.
|
||||
* A mount function called when the user navigates to this app's route.
|
||||
*
|
||||
* @param params {@link AppMountParameters}
|
||||
* @returns An unmounting function that will be called to unmount the application. See {@link AppUnmount}.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type AppMount = (params: AppMountParameters) => AppUnmount | Promise<AppUnmount>;
|
||||
|
||||
/**
|
||||
* A mount function called when the user navigates to this app's route.
|
||||
*
|
||||
* @remarks
|
||||
* When function has two arguments, it will be called with a {@link AppMountContext | context} as the first argument.
|
||||
* This behavior is **deprecated**, and consumers should instead use {@link CoreSetup.getStartServices}.
|
||||
*
|
||||
* @param context The mount context for this app. Deprecated, use {@link CoreSetup.getStartServices}.
|
||||
* @param params {@link AppMountParameters}
|
||||
* @returns An unmounting function that will be called to unmount the application. See {@link AppUnmount}.
|
||||
*
|
||||
* @deprecated
|
||||
* @public
|
||||
*/
|
||||
export type AppMountDeprecated = (
|
||||
context: AppMountContext,
|
||||
params: AppMountParameters
|
||||
) => AppUnmount | Promise<AppUnmount>;
|
||||
|
||||
/**
|
||||
* The context object received when applications are mounted to the DOM. Deprecated, use
|
||||
* {@link CoreSetup.getStartServices}.
|
||||
*
|
||||
* @deprecated
|
||||
* @public
|
||||
*/
|
||||
export interface AppMountContext {
|
||||
|
@ -192,9 +226,6 @@ export interface AppMountParameters {
|
|||
*/
|
||||
export type AppUnmount = () => void;
|
||||
|
||||
/** @internal */
|
||||
export type AppMounter = (params: AppMountParameters) => Promise<AppUnmount>;
|
||||
|
||||
/** @public */
|
||||
export interface ApplicationSetup {
|
||||
/**
|
||||
|
@ -205,14 +236,15 @@ export interface ApplicationSetup {
|
|||
|
||||
/**
|
||||
* Register a context provider for application mounting. Will only be available to applications that depend on the
|
||||
* plugin that registered this context.
|
||||
* plugin that registered this context. Deprecated, use {@link CoreSetup.getStartServices}.
|
||||
*
|
||||
* @deprecated
|
||||
* @param contextName - The key of {@link AppMountContext} this provider's return value should be attached to.
|
||||
* @param provider - A {@link IContextProvider} function
|
||||
*/
|
||||
registerMountContext<T extends keyof AppMountContext>(
|
||||
contextName: T,
|
||||
provider: IContextProvider<App['mount'], T>
|
||||
provider: IContextProvider<AppMountDeprecated, T>
|
||||
): void;
|
||||
}
|
||||
|
||||
|
@ -234,8 +266,9 @@ export interface InternalApplicationSetup {
|
|||
|
||||
/**
|
||||
* Register a context provider for application mounting. Will only be available to applications that depend on the
|
||||
* plugin that registered this context.
|
||||
* plugin that registered this context. Deprecated, use {@link CoreSetup.getStartServices}.
|
||||
*
|
||||
* @deprecated
|
||||
* @param pluginOpaqueId - The opaque ID of the plugin that is registering the context.
|
||||
* @param contextName - The key of {@link AppMountContext} this provider's return value should be attached to.
|
||||
* @param provider - A {@link IContextProvider} function
|
||||
|
@ -243,7 +276,7 @@ export interface InternalApplicationSetup {
|
|||
registerMountContext<T extends keyof AppMountContext>(
|
||||
pluginOpaqueId: PluginOpaqueId,
|
||||
contextName: T,
|
||||
provider: IContextProvider<App['mount'], T>
|
||||
provider: IContextProvider<AppMountDeprecated, T>
|
||||
): void;
|
||||
}
|
||||
|
||||
|
@ -272,15 +305,16 @@ export interface ApplicationStart {
|
|||
|
||||
/**
|
||||
* Register a context provider for application mounting. Will only be available to applications that depend on the
|
||||
* plugin that registered this context.
|
||||
* plugin that registered this context. Deprecated, use {@link CoreSetup.getStartServices}.
|
||||
*
|
||||
* @deprecated
|
||||
* @param pluginOpaqueId - The opaque ID of the plugin that is registering the context.
|
||||
* @param contextName - The key of {@link AppMountContext} this provider's return value should be attached to.
|
||||
* @param provider - A {@link IContextProvider} function
|
||||
*/
|
||||
registerMountContext<T extends keyof AppMountContext>(
|
||||
contextName: T,
|
||||
provider: IContextProvider<App['mount'], T>
|
||||
provider: IContextProvider<AppMountDeprecated, T>
|
||||
): void;
|
||||
}
|
||||
|
||||
|
@ -301,8 +335,9 @@ export interface InternalApplicationStart
|
|||
|
||||
/**
|
||||
* Register a context provider for application mounting. Will only be available to applications that depend on the
|
||||
* plugin that registered this context.
|
||||
* plugin that registered this context. Deprecated, use {@link CoreSetup.getStartServices}.
|
||||
*
|
||||
* @deprecated
|
||||
* @param pluginOpaqueId - The opaque ID of the plugin that is registering the context.
|
||||
* @param contextName - The key of {@link AppMountContext} this provider's return value should be attached to.
|
||||
* @param provider - A {@link IContextProvider} function
|
||||
|
@ -310,7 +345,7 @@ export interface InternalApplicationStart
|
|||
registerMountContext<T extends keyof AppMountContext>(
|
||||
pluginOpaqueId: PluginOpaqueId,
|
||||
contextName: T,
|
||||
provider: IContextProvider<App['mount'], T>
|
||||
provider: IContextProvider<AppMountDeprecated, T>
|
||||
): void;
|
||||
|
||||
// Internal APIs
|
||||
|
|
|
@ -21,12 +21,12 @@ import React from 'react';
|
|||
import { RouteComponentProps } from 'react-router-dom';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import { LegacyApp, AppMounter, AppUnmount } from '../types';
|
||||
import { LegacyApp, AppMount, AppUnmount } from '../types';
|
||||
import { HttpStart } from '../../http';
|
||||
import { AppNotFound } from './app_not_found_screen';
|
||||
|
||||
interface Props extends RouteComponentProps<{ appId: string }> {
|
||||
apps: ReadonlyMap<string, AppMounter>;
|
||||
apps: ReadonlyMap<string, AppMount>;
|
||||
legacyApps: ReadonlyMap<string, LegacyApp>;
|
||||
basePath: HttpStart['basePath'];
|
||||
currentAppId$: Subject<string | undefined>;
|
||||
|
|
|
@ -22,12 +22,12 @@ import React from 'react';
|
|||
import { Router, Route } from 'react-router-dom';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import { LegacyApp, AppMounter } from '../types';
|
||||
import { LegacyApp, AppMount } from '../types';
|
||||
import { AppContainer } from './app_container';
|
||||
import { HttpStart } from '../../http';
|
||||
|
||||
interface Props {
|
||||
apps: ReadonlyMap<string, AppMounter>;
|
||||
apps: ReadonlyMap<string, AppMount>;
|
||||
legacyApps: ReadonlyMap<string, LegacyApp>;
|
||||
basePath: HttpStart['basePath'];
|
||||
currentAppId$: Subject<string | undefined>;
|
||||
|
|
|
@ -64,7 +64,7 @@ export interface CoreContext {
|
|||
}
|
||||
|
||||
/** @internal */
|
||||
export interface InternalCoreSetup extends Omit<CoreSetup, 'application'> {
|
||||
export interface InternalCoreSetup extends Omit<CoreSetup, 'application' | 'getStartServices'> {
|
||||
application: InternalApplicationSetup;
|
||||
injectedMetadata: InjectedMetadataSetup;
|
||||
}
|
||||
|
@ -253,11 +253,11 @@ export class CoreSystem {
|
|||
docLinks,
|
||||
http,
|
||||
i18n,
|
||||
injectedMetadata: pick(injectedMetadata, ['getInjectedVar']),
|
||||
notifications,
|
||||
overlays,
|
||||
savedObjects,
|
||||
uiSettings,
|
||||
injectedMetadata: pick(injectedMetadata, ['getInjectedVar']),
|
||||
}));
|
||||
|
||||
const core: InternalCoreStart = {
|
||||
|
|
|
@ -80,7 +80,17 @@ import {
|
|||
export { CoreContext, CoreSystem } from './core_system';
|
||||
export { RecursiveReadonly } from '../utils';
|
||||
|
||||
export { App, AppBase, AppUnmount, AppMountContext, AppMountParameters } from './application';
|
||||
export {
|
||||
ApplicationSetup,
|
||||
ApplicationStart,
|
||||
App,
|
||||
AppBase,
|
||||
AppMount,
|
||||
AppMountDeprecated,
|
||||
AppUnmount,
|
||||
AppMountContext,
|
||||
AppMountParameters,
|
||||
} from './application';
|
||||
|
||||
export {
|
||||
SavedObjectsBatchResponse,
|
||||
|
@ -146,10 +156,13 @@ export { MountPoint, UnmountCallback } from './types';
|
|||
* navigation in the generated docs until there's a fix for
|
||||
* https://github.com/Microsoft/web-build-tools/issues/1237
|
||||
*/
|
||||
export interface CoreSetup {
|
||||
export interface CoreSetup<TPluginsStart extends object = object> {
|
||||
/** {@link ApplicationSetup} */
|
||||
application: ApplicationSetup;
|
||||
/** {@link ContextSetup} */
|
||||
/**
|
||||
* {@link ContextSetup}
|
||||
* @deprecated
|
||||
*/
|
||||
context: ContextSetup;
|
||||
/** {@link FatalErrorsSetup} */
|
||||
fatalErrors: FatalErrorsSetup;
|
||||
|
@ -168,6 +181,13 @@ export interface CoreSetup {
|
|||
injectedMetadata: {
|
||||
getInjectedVar: (name: string, defaultValue?: any) => unknown;
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows plugins to get access to APIs available in start inside async
|
||||
* handlers, such as {@link App.mount}. Promise will not resolve until Core
|
||||
* and plugin dependencies have completed `start`.
|
||||
*/
|
||||
getStartServices(): Promise<[CoreStart, TPluginsStart]>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -219,7 +239,7 @@ export interface CoreStart {
|
|||
* @public
|
||||
* @deprecated
|
||||
*/
|
||||
export interface LegacyCoreSetup extends CoreSetup {
|
||||
export interface LegacyCoreSetup extends CoreSetup<any> {
|
||||
/** @deprecated */
|
||||
injectedMetadata: InjectedMetadataSetup;
|
||||
}
|
||||
|
@ -240,8 +260,6 @@ export interface LegacyCoreStart extends CoreStart {
|
|||
}
|
||||
|
||||
export {
|
||||
ApplicationSetup,
|
||||
ApplicationStart,
|
||||
Capabilities,
|
||||
ChromeBadge,
|
||||
ChromeBrand,
|
||||
|
|
|
@ -169,6 +169,20 @@ describe('#start()', () => {
|
|||
expect(mockUiNewPlatformStart).toHaveBeenCalledWith(expect.any(Object), {});
|
||||
});
|
||||
|
||||
it('resolves getStartServices with core and plugin APIs', async () => {
|
||||
const legacyPlatform = new LegacyPlatformService({
|
||||
...defaultParams,
|
||||
});
|
||||
|
||||
legacyPlatform.setup(defaultSetupDeps);
|
||||
legacyPlatform.start(defaultStartDeps);
|
||||
|
||||
const { getStartServices } = mockUiNewPlatformSetup.mock.calls[0][0];
|
||||
const [coreStart, pluginsStart] = await getStartServices();
|
||||
expect(coreStart).toEqual(expect.any(Object));
|
||||
expect(pluginsStart).toBe(defaultStartDeps.plugins);
|
||||
});
|
||||
|
||||
describe('useLegacyTestHarness = false', () => {
|
||||
it('passes the targetDomElement to ui/chrome', () => {
|
||||
const legacyPlatform = new LegacyPlatformService({
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
|
||||
import angular from 'angular';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
import { InternalCoreSetup, InternalCoreStart } from '../core_system';
|
||||
import { LegacyCoreSetup, LegacyCoreStart, MountPoint } from '../';
|
||||
|
||||
|
@ -55,6 +57,8 @@ export class LegacyPlatformService {
|
|||
public readonly legacyId = Symbol();
|
||||
private bootstrapModule?: BootstrapModule;
|
||||
private targetDomElement?: HTMLElement;
|
||||
private readonly startDependencies$ = new Subject<[LegacyCoreStart, object]>();
|
||||
private readonly startDependencies = this.startDependencies$.pipe(first()).toPromise();
|
||||
|
||||
constructor(private readonly params: LegacyPlatformParams) {}
|
||||
|
||||
|
@ -75,6 +79,7 @@ export class LegacyPlatformService {
|
|||
|
||||
const legacyCore: LegacyCoreSetup = {
|
||||
...core,
|
||||
getStartServices: () => this.startDependencies,
|
||||
application: {
|
||||
register: notSupported(`core.application.register()`),
|
||||
registerMountContext: notSupported(`core.application.registerMountContext()`),
|
||||
|
@ -120,6 +125,8 @@ export class LegacyPlatformService {
|
|||
},
|
||||
};
|
||||
|
||||
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
|
||||
require('ui/new_platform').__start__(legacyCore, plugins);
|
||||
|
|
|
@ -46,6 +46,9 @@ function createCoreSetupMock({ basePath = '' } = {}) {
|
|||
application: applicationServiceMock.createSetupContract(),
|
||||
context: contextServiceMock.createSetupContract(),
|
||||
fatalErrors: fatalErrorsServiceMock.createSetupContract(),
|
||||
getStartServices: jest.fn<Promise<[ReturnType<typeof createCoreStartMock>, object]>, []>(() =>
|
||||
Promise.resolve([createCoreStartMock({ basePath }), {}])
|
||||
),
|
||||
http: httpServiceMock.createSetupContract({ basePath }),
|
||||
notifications: notificationServiceMock.createSetupContract(),
|
||||
uiSettings: uiSettingsServiceMock.createSetupContract(),
|
||||
|
@ -75,6 +78,7 @@ function createCoreStartMock({ basePath = '' } = {}) {
|
|||
|
||||
return mock;
|
||||
}
|
||||
|
||||
function pluginInitializerContextMock() {
|
||||
const mock: PluginInitializerContext = {
|
||||
opaqueId: Symbol(),
|
||||
|
|
|
@ -106,6 +106,33 @@ describe('PluginWrapper', () => {
|
|||
expect(mockPlugin.start).toHaveBeenCalledWith(context, deps);
|
||||
});
|
||||
|
||||
test("`start` resolves `startDependencies` Promise after plugin's start", async () => {
|
||||
expect.assertions(2);
|
||||
|
||||
let startDependenciesResolved = false;
|
||||
mockPluginLoader.mockResolvedValueOnce(() => ({
|
||||
setup: jest.fn(),
|
||||
start: async () => {
|
||||
// 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);
|
||||
},
|
||||
}));
|
||||
await plugin.load(addBasePath);
|
||||
await plugin.setup({} as any, {} as any);
|
||||
const context = { any: 'thing' } as any;
|
||||
const deps = { otherDep: 'value' };
|
||||
|
||||
// Add promise callback prior to calling `start` to ensure calls in `setup` will not resolve before `start` is
|
||||
// called.
|
||||
const startDependenciesCheck = plugin.startDependencies.then(res => {
|
||||
startDependenciesResolved = true;
|
||||
expect(res).toEqual([context, deps]);
|
||||
});
|
||||
await plugin.start(context, deps);
|
||||
await startDependenciesCheck;
|
||||
});
|
||||
|
||||
test('`stop` fails if plugin is not setup up', async () => {
|
||||
expect(() => plugin.stop()).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Plugin \\"plugin-a\\" can't be stopped since it isn't set up."`
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { Subject } from 'rxjs';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { DiscoveredPlugin, PluginOpaqueId } from '../../server';
|
||||
import { PluginInitializerContext } from './plugin_context';
|
||||
import { loadPluginBundle } from './plugin_loader';
|
||||
|
@ -33,7 +35,7 @@ export interface Plugin<
|
|||
TPluginsSetup extends object = object,
|
||||
TPluginsStart extends object = object
|
||||
> {
|
||||
setup(core: CoreSetup, plugins: TPluginsSetup): TSetup | Promise<TSetup>;
|
||||
setup(core: CoreSetup<TPluginsStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>;
|
||||
start(core: CoreStart, plugins: TPluginsStart): TStart | Promise<TStart>;
|
||||
stop?(): void;
|
||||
}
|
||||
|
@ -70,6 +72,9 @@ export class PluginWrapper<
|
|||
private initializer?: PluginInitializer<TSetup, TStart, TPluginsSetup, TPluginsStart>;
|
||||
private instance?: Plugin<TSetup, TStart, TPluginsSetup, TPluginsStart>;
|
||||
|
||||
private readonly startDependencies$ = new Subject<[CoreStart, TPluginsStart]>();
|
||||
public readonly startDependencies = this.startDependencies$.pipe(first()).toPromise();
|
||||
|
||||
constructor(
|
||||
public readonly discoveredPlugin: DiscoveredPlugin,
|
||||
public readonly opaqueId: PluginOpaqueId,
|
||||
|
@ -100,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, plugins: TPluginsSetup) {
|
||||
public async setup(setupContext: CoreSetup<TPluginsStart>, plugins: TPluginsSetup) {
|
||||
this.instance = await this.createPluginInstance();
|
||||
|
||||
return await this.instance.setup(setupContext, plugins);
|
||||
|
@ -118,7 +123,11 @@ export class PluginWrapper<
|
|||
throw new Error(`Plugin "${this.name}" can't be started since it isn't set up.`);
|
||||
}
|
||||
|
||||
return await this.instance.start(startContext, plugins);
|
||||
const startContract = await this.instance.start(startContext, plugins);
|
||||
|
||||
this.startDependencies$.next([startContext, plugins]);
|
||||
|
||||
return startContract;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -107,6 +107,7 @@ export function createPluginSetupContext<
|
|||
injectedMetadata: {
|
||||
getInjectedVar: deps.injectedMetadata.getInjectedVar,
|
||||
},
|
||||
getStartServices: () => plugin.startDependencies,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ describe('PluginsService', () => {
|
|||
mockSetupContext = {
|
||||
...mockSetupDeps,
|
||||
application: expect.any(Object),
|
||||
getStartServices: expect.any(Function),
|
||||
};
|
||||
mockStartDeps = {
|
||||
application: applicationServiceMock.createInternalStartContract(),
|
||||
|
|
|
@ -19,7 +19,7 @@ import { UserProvidedValues as UserProvidedValues_2 } from 'src/core/server/type
|
|||
// @public
|
||||
export interface App extends AppBase {
|
||||
chromeless?: boolean;
|
||||
mount: (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise<AppUnmount>;
|
||||
mount: AppMount | AppMountDeprecated;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
|
@ -37,7 +37,8 @@ export interface AppBase {
|
|||
// @public (undocumented)
|
||||
export interface ApplicationSetup {
|
||||
register(app: App): void;
|
||||
registerMountContext<T extends keyof AppMountContext>(contextName: T, provider: IContextProvider<App['mount'], T>): void;
|
||||
// @deprecated
|
||||
registerMountContext<T extends keyof AppMountContext>(contextName: T, provider: IContextProvider<AppMountDeprecated, T>): void;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
|
@ -50,10 +51,14 @@ export interface ApplicationStart {
|
|||
path?: string;
|
||||
state?: any;
|
||||
}): void;
|
||||
registerMountContext<T extends keyof AppMountContext>(contextName: T, provider: IContextProvider<App['mount'], T>): void;
|
||||
// @deprecated
|
||||
registerMountContext<T extends keyof AppMountContext>(contextName: T, provider: IContextProvider<AppMountDeprecated, T>): void;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type AppMount = (params: AppMountParameters) => AppUnmount | Promise<AppUnmount>;
|
||||
|
||||
// @public @deprecated
|
||||
export interface AppMountContext {
|
||||
core: {
|
||||
application: Pick<ApplicationStart, 'capabilities' | 'navigateToApp'>;
|
||||
|
@ -71,6 +76,9 @@ export interface AppMountContext {
|
|||
};
|
||||
}
|
||||
|
||||
// @public @deprecated
|
||||
export type AppMountDeprecated = (context: AppMountContext, params: AppMountParameters) => AppUnmount | Promise<AppUnmount>;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface AppMountParameters {
|
||||
appBasePath: string;
|
||||
|
@ -275,13 +283,14 @@ export interface CoreContext {
|
|||
}
|
||||
|
||||
// @public
|
||||
export interface CoreSetup {
|
||||
export interface CoreSetup<TPluginsStart extends object = object> {
|
||||
// (undocumented)
|
||||
application: ApplicationSetup;
|
||||
// (undocumented)
|
||||
// @deprecated (undocumented)
|
||||
context: ContextSetup;
|
||||
// (undocumented)
|
||||
fatalErrors: FatalErrorsSetup;
|
||||
getStartServices(): Promise<[CoreStart, TPluginsStart]>;
|
||||
// (undocumented)
|
||||
http: HttpSetup;
|
||||
// @deprecated
|
||||
|
@ -653,7 +662,7 @@ export interface IUiSettingsClient {
|
|||
}
|
||||
|
||||
// @public @deprecated
|
||||
export interface LegacyCoreSetup extends CoreSetup {
|
||||
export interface LegacyCoreSetup extends CoreSetup<any> {
|
||||
// Warning: (ae-forgotten-export) The symbol "InjectedMetadataSetup" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// @deprecated (undocumented)
|
||||
|
@ -749,7 +758,7 @@ export interface PackageInfo {
|
|||
// @public
|
||||
export interface Plugin<TSetup = void, TStart = void, TPluginsSetup extends object = object, TPluginsStart extends object = object> {
|
||||
// (undocumented)
|
||||
setup(core: CoreSetup, plugins: TPluginsSetup): TSetup | Promise<TSetup>;
|
||||
setup(core: CoreSetup<TPluginsStart>, plugins: TPluginsSetup): TSetup | Promise<TSetup>;
|
||||
// (undocumented)
|
||||
start(core: CoreStart, plugins: TPluginsStart): TStart | Promise<TStart>;
|
||||
// (undocumented)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { App, AppUnmount } from 'kibana/public';
|
||||
import { App, AppUnmount, AppMountDeprecated } from 'kibana/public';
|
||||
import { UIRoutes } from 'ui/routes';
|
||||
import { ILocationService, IScope } from 'angular';
|
||||
import { npStart } from 'ui/new_platform';
|
||||
|
@ -68,7 +68,10 @@ export class LocalApplicationService {
|
|||
isUnmounted = true;
|
||||
});
|
||||
(async () => {
|
||||
unmountHandler = await app.mount({ core: npStart.core }, { element, appBasePath: '' });
|
||||
const params = { element, appBasePath: '' };
|
||||
unmountHandler = isAppMountDeprecated(app.mount)
|
||||
? await app.mount({ core: npStart.core }, params)
|
||||
: await app.mount(params);
|
||||
// immediately unmount app if scope got destroyed in the meantime
|
||||
if (isUnmounted) {
|
||||
unmountHandler();
|
||||
|
@ -90,3 +93,8 @@ export class LocalApplicationService {
|
|||
}
|
||||
|
||||
export const localApplicationService = new LocalApplicationService();
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,26 @@ describe('ui/new_platform', () => {
|
|||
const scopeMock = { $on: jest.fn() };
|
||||
const elementMock = [document.createElement('div')];
|
||||
|
||||
controller(scopeMock, elementMock);
|
||||
expect(mountMock).toHaveBeenCalledWith({
|
||||
element: elementMock[0],
|
||||
appBasePath: '/test/base/path/app/test',
|
||||
});
|
||||
});
|
||||
|
||||
test('controller calls deprecated context app.mount when invoked', () => {
|
||||
const unmountMock = jest.fn();
|
||||
// Two arguments changes how this is called.
|
||||
const mountMock = jest.fn((context, params) => unmountMock);
|
||||
legacyAppRegister({
|
||||
id: 'test',
|
||||
title: 'Test',
|
||||
mount: mountMock,
|
||||
});
|
||||
const controller = setRootControllerMock.mock.calls[0][1];
|
||||
const scopeMock = { $on: jest.fn() };
|
||||
const elementMock = [document.createElement('div')];
|
||||
|
||||
controller(scopeMock, elementMock);
|
||||
expect(mountMock).toHaveBeenCalledWith(expect.any(Object), {
|
||||
element: elementMock[0],
|
||||
|
|
|
@ -20,7 +20,7 @@ import { IScope } from 'angular';
|
|||
|
||||
import { IUiActionsStart, IUiActionsSetup } from 'src/plugins/ui_actions/public';
|
||||
import { IEmbeddableStart, IEmbeddableSetup } from 'src/plugins/embeddable/public';
|
||||
import { LegacyCoreSetup, LegacyCoreStart, App } from '../../../../core/public';
|
||||
import { LegacyCoreSetup, LegacyCoreStart, App, AppMountDeprecated } from '../../../../core/public';
|
||||
import { Plugin as DataPlugin } from '../../../../plugins/data/public';
|
||||
import { Plugin as ExpressionsPlugin } from '../../../../plugins/expressions/public';
|
||||
import {
|
||||
|
@ -111,13 +111,18 @@ export const legacyAppRegister = (app: App) => {
|
|||
|
||||
// Root controller cannot return a Promise so use an internal async function and call it immediately
|
||||
(async () => {
|
||||
const unmount = await app.mount(
|
||||
{ core: npStart.core },
|
||||
{ element, appBasePath: npSetup.core.http.basePath.prepend(`/app/${app.id}`) }
|
||||
);
|
||||
const params = { element, appBasePath: npSetup.core.http.basePath.prepend(`/app/${app.id}`) };
|
||||
const unmount = isAppMountDeprecated(app.mount)
|
||||
? await app.mount({ core: npStart.core }, params)
|
||||
: await app.mount(params);
|
||||
$scope.$on('$destroy', () => {
|
||||
unmount();
|
||||
});
|
||||
})();
|
||||
});
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import * as React from 'react';
|
|||
import ReactDOM from 'react-dom';
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
import { AppMountContext } from 'kibana/public';
|
||||
import { AppMountContext, AppMountDeprecated } from 'kibana/public';
|
||||
import { DevTool } from './plugin';
|
||||
|
||||
interface DevToolsWrapperProps {
|
||||
|
@ -91,10 +91,10 @@ function DevToolsWrapper({
|
|||
if (mountedTool.current) {
|
||||
mountedTool.current.unmountHandler();
|
||||
}
|
||||
const unmountHandler = await activeDevTool.mount(appMountContext, {
|
||||
element,
|
||||
appBasePath: '',
|
||||
});
|
||||
const params = { element, appBasePath: '' };
|
||||
const unmountHandler = isAppMountDeprecated(activeDevTool.mount)
|
||||
? await activeDevTool.mount(appMountContext, params)
|
||||
: await activeDevTool.mount(params);
|
||||
mountedTool.current = {
|
||||
devTool: activeDevTool,
|
||||
mountpoint: element,
|
||||
|
@ -182,3 +182,8 @@ export function renderApp(
|
|||
|
||||
return () => ReactDOM.unmountComponentAtNode(element);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ declare global {
|
|||
interface Window {
|
||||
corePluginB?: string;
|
||||
hasAccessToInjectedMetadata?: boolean;
|
||||
receivedStartServices?: boolean;
|
||||
env?: PluginInitializerContext['env'];
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +41,9 @@ export class CorePluginBPlugin
|
|||
public setup(core: CoreSetup, deps: CorePluginBDeps) {
|
||||
window.corePluginB = `Plugin A said: ${deps.core_plugin_a.getGreeting()}`;
|
||||
window.hasAccessToInjectedMetadata = 'getInjectedVar' in core.injectedMetadata;
|
||||
core.getStartServices().then(([coreStart, plugins]) => {
|
||||
window.receivedStartServices = 'overlays' in coreStart;
|
||||
});
|
||||
|
||||
core.application.register({
|
||||
id: 'bar',
|
||||
|
|
|
@ -22,8 +22,8 @@ import { npSetup } from 'ui/new_platform';
|
|||
npSetup.core.application.register({
|
||||
id: 'core_legacy_compat',
|
||||
title: 'Core Legacy Compat',
|
||||
async mount(...args) {
|
||||
async mount(context, params) {
|
||||
const { renderApp } = await import('./application');
|
||||
return renderApp(...args);
|
||||
return renderApp(context, params);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -36,28 +36,41 @@ export default function({ getService, getPageObjects }: PluginFunctionalProvider
|
|||
expect(corePluginB).to.equal(`Plugin A said: Hello from Plugin A!`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('have injectedMetadata service provided', function describeIndexTests() {
|
||||
before(async () => {
|
||||
await PageObjects.common.navigateToApp('bar');
|
||||
});
|
||||
|
||||
it('should attach string to window.corePluginB', async () => {
|
||||
it('should attach boolean to window.hasAccessToInjectedMetadata', async () => {
|
||||
const hasAccessToInjectedMetadata = await browser.execute(
|
||||
'return window.hasAccessToInjectedMetadata'
|
||||
);
|
||||
expect(hasAccessToInjectedMetadata).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('have env data provided', function describeIndexTests() {
|
||||
before(async () => {
|
||||
await PageObjects.common.navigateToApp('bar');
|
||||
});
|
||||
|
||||
it('should attach pluginContext to window.corePluginB', async () => {
|
||||
it('should attach pluginContext to window.env', async () => {
|
||||
const envData: any = await browser.execute('return window.env');
|
||||
expect(envData.mode.dev).to.be(true);
|
||||
expect(envData.packageInfo.version).to.be.a('string');
|
||||
});
|
||||
});
|
||||
|
||||
describe('have access to start services via coreSetup.getStartServices', function describeIndexTests() {
|
||||
before(async () => {
|
||||
await PageObjects.common.navigateToApp('bar');
|
||||
});
|
||||
|
||||
it('should attach boolean to window.receivedStartServices', async () => {
|
||||
const receivedStartServices = await browser.execute('return window.receivedStartServices');
|
||||
expect(receivedStartServices).to.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue