Expose package info to NP plugins (#48101) (#48215)

* provide packageInfo to server plugins

* provide env to kbn server

* provide env to client plugins

* update server mocks and tests

* update client mocks and tests

* add integration test

* regen docs

* remove weird file

* export types for the client from special folder

* env should not affect test ourcome
This commit is contained in:
Mikhail Shustov 2019-10-15 15:42:22 +02:00 committed by GitHub
parent cf7f2aa8c5
commit 1a3c2e3ba2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
57 changed files with 498 additions and 65 deletions

View file

@ -149,6 +149,7 @@ module.exports = {
'src/core/server/**/*', 'src/core/server/**/*',
'!src/core/server/index.ts', '!src/core/server/index.ts',
'!src/core/server/mocks.ts', '!src/core/server/mocks.ts',
'!src/core/server/types.ts',
'!src/core/server/*.test.mocks.ts', '!src/core/server/*.test.mocks.ts',
'src/plugins/**/public/**/*', 'src/plugins/**/public/**/*',

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [EnvironmentMode](./kibana-plugin-public.environmentmode.md) &gt; [dev](./kibana-plugin-public.environmentmode.dev.md)
## EnvironmentMode.dev property
<b>Signature:</b>
```typescript
dev: boolean;
```

View file

@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [EnvironmentMode](./kibana-plugin-public.environmentmode.md)
## EnvironmentMode interface
<b>Signature:</b>
```typescript
export interface EnvironmentMode
```
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [dev](./kibana-plugin-public.environmentmode.dev.md) | <code>boolean</code> | |
| [name](./kibana-plugin-public.environmentmode.name.md) | <code>'development' &#124; 'production'</code> | |
| [prod](./kibana-plugin-public.environmentmode.prod.md) | <code>boolean</code> | |

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [EnvironmentMode](./kibana-plugin-public.environmentmode.md) &gt; [name](./kibana-plugin-public.environmentmode.name.md)
## EnvironmentMode.name property
<b>Signature:</b>
```typescript
name: 'development' | 'production';
```

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [EnvironmentMode](./kibana-plugin-public.environmentmode.md) &gt; [prod](./kibana-plugin-public.environmentmode.prod.md)
## EnvironmentMode.prod property
<b>Signature:</b>
```typescript
prod: boolean;
```

View file

@ -46,6 +46,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [CoreSetup](./kibana-plugin-public.coresetup.md) | Core services exposed to the <code>Plugin</code> setup lifecycle | | [CoreSetup](./kibana-plugin-public.coresetup.md) | Core services exposed to the <code>Plugin</code> setup lifecycle |
| [CoreStart](./kibana-plugin-public.corestart.md) | Core services exposed to the <code>Plugin</code> start lifecycle | | [CoreStart](./kibana-plugin-public.corestart.md) | Core services exposed to the <code>Plugin</code> start lifecycle |
| [DocLinksStart](./kibana-plugin-public.doclinksstart.md) | | | [DocLinksStart](./kibana-plugin-public.doclinksstart.md) | |
| [EnvironmentMode](./kibana-plugin-public.environmentmode.md) | |
| [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) | | | [ErrorToastOptions](./kibana-plugin-public.errortoastoptions.md) | |
| [FatalErrorInfo](./kibana-plugin-public.fatalerrorinfo.md) | Represents the <code>message</code> and <code>stack</code> of a fatal Error | | [FatalErrorInfo](./kibana-plugin-public.fatalerrorinfo.md) | Represents the <code>message</code> and <code>stack</code> of a fatal Error |
| [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | | [FatalErrorsSetup](./kibana-plugin-public.fatalerrorssetup.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. |
@ -68,6 +69,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) | | | [OverlayBannersStart](./kibana-plugin-public.overlaybannersstart.md) | |
| [OverlayRef](./kibana-plugin-public.overlayref.md) | | | [OverlayRef](./kibana-plugin-public.overlayref.md) | |
| [OverlayStart](./kibana-plugin-public.overlaystart.md) | | | [OverlayStart](./kibana-plugin-public.overlaystart.md) | |
| [PackageInfo](./kibana-plugin-public.packageinfo.md) | |
| [Plugin](./kibana-plugin-public.plugin.md) | The interface that should be returned by a <code>PluginInitializer</code>. | | [Plugin](./kibana-plugin-public.plugin.md) | The interface that should be returned by a <code>PluginInitializer</code>. |
| [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) | The available core services passed to a <code>PluginInitializer</code> | | [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) | The available core services passed to a <code>PluginInitializer</code> |
| [SavedObject](./kibana-plugin-public.savedobject.md) | | | [SavedObject](./kibana-plugin-public.savedobject.md) | |

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [PackageInfo](./kibana-plugin-public.packageinfo.md) &gt; [branch](./kibana-plugin-public.packageinfo.branch.md)
## PackageInfo.branch property
<b>Signature:</b>
```typescript
branch: string;
```

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [PackageInfo](./kibana-plugin-public.packageinfo.md) &gt; [buildNum](./kibana-plugin-public.packageinfo.buildnum.md)
## PackageInfo.buildNum property
<b>Signature:</b>
```typescript
buildNum: number;
```

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [PackageInfo](./kibana-plugin-public.packageinfo.md) &gt; [buildSha](./kibana-plugin-public.packageinfo.buildsha.md)
## PackageInfo.buildSha property
<b>Signature:</b>
```typescript
buildSha: string;
```

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [PackageInfo](./kibana-plugin-public.packageinfo.md) &gt; [dist](./kibana-plugin-public.packageinfo.dist.md)
## PackageInfo.dist property
<b>Signature:</b>
```typescript
dist: boolean;
```

View file

@ -0,0 +1,23 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [PackageInfo](./kibana-plugin-public.packageinfo.md)
## PackageInfo interface
<b>Signature:</b>
```typescript
export interface PackageInfo
```
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [branch](./kibana-plugin-public.packageinfo.branch.md) | <code>string</code> | |
| [buildNum](./kibana-plugin-public.packageinfo.buildnum.md) | <code>number</code> | |
| [buildSha](./kibana-plugin-public.packageinfo.buildsha.md) | <code>string</code> | |
| [dist](./kibana-plugin-public.packageinfo.dist.md) | <code>boolean</code> | |
| [version](./kibana-plugin-public.packageinfo.version.md) | <code>string</code> | |

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [PackageInfo](./kibana-plugin-public.packageinfo.md) &gt; [version](./kibana-plugin-public.packageinfo.version.md)
## PackageInfo.version property
<b>Signature:</b>
```typescript
version: string;
```

View file

@ -0,0 +1,14 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [PluginInitializerContext](./kibana-plugin-public.plugininitializercontext.md) &gt; [env](./kibana-plugin-public.plugininitializercontext.env.md)
## PluginInitializerContext.env property
<b>Signature:</b>
```typescript
readonly env: {
mode: Readonly<EnvironmentMode>;
packageInfo: Readonly<PackageInfo>;
};
```

View file

@ -16,5 +16,6 @@ export interface PluginInitializerContext
| Property | Type | Description | | Property | Type | Description |
| --- | --- | --- | | --- | --- | --- |
| [env](./kibana-plugin-public.plugininitializercontext.env.md) | <code>{</code><br/><code> mode: Readonly&lt;EnvironmentMode&gt;;</code><br/><code> packageInfo: Readonly&lt;PackageInfo&gt;;</code><br/><code> }</code> | |
| [opaqueId](./kibana-plugin-public.plugininitializercontext.opaqueid.md) | <code>PluginOpaqueId</code> | A symbol used to identify this plugin in the system. Needed when registering handlers or context providers. | | [opaqueId](./kibana-plugin-public.plugininitializercontext.opaqueid.md) | <code>PluginOpaqueId</code> | A symbol used to identify this plugin in the system. Needed when registering handlers or context providers. |

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [EnvironmentMode](./kibana-plugin-server.environmentmode.md) &gt; [dev](./kibana-plugin-server.environmentmode.dev.md)
## EnvironmentMode.dev property
<b>Signature:</b>
```typescript
dev: boolean;
```

View file

@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [EnvironmentMode](./kibana-plugin-server.environmentmode.md)
## EnvironmentMode interface
<b>Signature:</b>
```typescript
export interface EnvironmentMode
```
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [dev](./kibana-plugin-server.environmentmode.dev.md) | <code>boolean</code> | |
| [name](./kibana-plugin-server.environmentmode.name.md) | <code>'development' &#124; 'production'</code> | |
| [prod](./kibana-plugin-server.environmentmode.prod.md) | <code>boolean</code> | |

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [EnvironmentMode](./kibana-plugin-server.environmentmode.md) &gt; [name](./kibana-plugin-server.environmentmode.name.md)
## EnvironmentMode.name property
<b>Signature:</b>
```typescript
name: 'development' | 'production';
```

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [EnvironmentMode](./kibana-plugin-server.environmentmode.md) &gt; [prod](./kibana-plugin-server.environmentmode.prod.md)
## EnvironmentMode.prod property
<b>Signature:</b>
```typescript
prod: boolean;
```

View file

@ -49,6 +49,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. | | [DiscoveredPlugin](./kibana-plugin-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. |
| [ElasticsearchError](./kibana-plugin-server.elasticsearcherror.md) | | | [ElasticsearchError](./kibana-plugin-server.elasticsearcherror.md) | |
| [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) | | | [ElasticsearchServiceSetup](./kibana-plugin-server.elasticsearchservicesetup.md) | |
| [EnvironmentMode](./kibana-plugin-server.environmentmode.md) | |
| [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) | HTTP response parameters | | [ErrorHttpResponseOptions](./kibana-plugin-server.errorhttpresponseoptions.md) | HTTP response parameters |
| [FakeRequest](./kibana-plugin-server.fakerequest.md) | Fake request object created manually by Kibana plugins. | | [FakeRequest](./kibana-plugin-server.fakerequest.md) | Fake request object created manually by Kibana plugins. |
| [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) | HTTP response parameters | | [HttpResponseOptions](./kibana-plugin-server.httpresponseoptions.md) | HTTP response parameters |
@ -67,6 +68,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [LogMeta](./kibana-plugin-server.logmeta.md) | Contextual metadata | | [LogMeta](./kibana-plugin-server.logmeta.md) | Contextual metadata |
| [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md) | A tool set defining an outcome of OnPostAuth interceptor for incoming request. | | [OnPostAuthToolkit](./kibana-plugin-server.onpostauthtoolkit.md) | A tool set defining an outcome of OnPostAuth interceptor for incoming request. |
| [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. | | [OnPreAuthToolkit](./kibana-plugin-server.onpreauthtoolkit.md) | A tool set defining an outcome of OnPreAuth interceptor for incoming request. |
| [PackageInfo](./kibana-plugin-server.packageinfo.md) | |
| [Plugin](./kibana-plugin-server.plugin.md) | The interface that should be returned by a <code>PluginInitializer</code>. | | [Plugin](./kibana-plugin-server.plugin.md) | The interface that should be returned by a <code>PluginInitializer</code>. |
| [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) | Context that's available to plugins during initialization stage. | | [PluginInitializerContext](./kibana-plugin-server.plugininitializercontext.md) | Context that's available to plugins during initialization stage. |
| [PluginManifest](./kibana-plugin-server.pluginmanifest.md) | Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. | | [PluginManifest](./kibana-plugin-server.pluginmanifest.md) | Describes the set of required and optional properties plugin can define in its mandatory JSON manifest file. |

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [PackageInfo](./kibana-plugin-server.packageinfo.md) &gt; [branch](./kibana-plugin-server.packageinfo.branch.md)
## PackageInfo.branch property
<b>Signature:</b>
```typescript
branch: string;
```

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [PackageInfo](./kibana-plugin-server.packageinfo.md) &gt; [buildNum](./kibana-plugin-server.packageinfo.buildnum.md)
## PackageInfo.buildNum property
<b>Signature:</b>
```typescript
buildNum: number;
```

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [PackageInfo](./kibana-plugin-server.packageinfo.md) &gt; [buildSha](./kibana-plugin-server.packageinfo.buildsha.md)
## PackageInfo.buildSha property
<b>Signature:</b>
```typescript
buildSha: string;
```

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [PackageInfo](./kibana-plugin-server.packageinfo.md) &gt; [dist](./kibana-plugin-server.packageinfo.dist.md)
## PackageInfo.dist property
<b>Signature:</b>
```typescript
dist: boolean;
```

View file

@ -0,0 +1,23 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [PackageInfo](./kibana-plugin-server.packageinfo.md)
## PackageInfo interface
<b>Signature:</b>
```typescript
export interface PackageInfo
```
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [branch](./kibana-plugin-server.packageinfo.branch.md) | <code>string</code> | |
| [buildNum](./kibana-plugin-server.packageinfo.buildnum.md) | <code>number</code> | |
| [buildSha](./kibana-plugin-server.packageinfo.buildsha.md) | <code>string</code> | |
| [dist](./kibana-plugin-server.packageinfo.dist.md) | <code>boolean</code> | |
| [version](./kibana-plugin-server.packageinfo.version.md) | <code>string</code> | |

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-server](./kibana-plugin-server.md) &gt; [PackageInfo](./kibana-plugin-server.packageinfo.md) &gt; [version](./kibana-plugin-server.packageinfo.version.md)
## PackageInfo.version property
<b>Signature:</b>
```typescript
version: string;
```

View file

@ -9,5 +9,6 @@
```typescript ```typescript
env: { env: {
mode: EnvironmentMode; mode: EnvironmentMode;
packageInfo: Readonly<PackageInfo>;
}; };
``` ```

View file

@ -17,7 +17,7 @@ export interface PluginInitializerContext<ConfigSchema = unknown>
| Property | Type | Description | | Property | Type | Description |
| --- | --- | --- | | --- | --- | --- |
| [config](./kibana-plugin-server.plugininitializercontext.config.md) | <code>{</code><br/><code> create: &lt;T = ConfigSchema&gt;() =&gt; Observable&lt;T&gt;;</code><br/><code> createIfExists: &lt;T = ConfigSchema&gt;() =&gt; Observable&lt;T &#124; undefined&gt;;</code><br/><code> }</code> | | | [config](./kibana-plugin-server.plugininitializercontext.config.md) | <code>{</code><br/><code> create: &lt;T = ConfigSchema&gt;() =&gt; Observable&lt;T&gt;;</code><br/><code> createIfExists: &lt;T = ConfigSchema&gt;() =&gt; Observable&lt;T &#124; undefined&gt;;</code><br/><code> }</code> | |
| [env](./kibana-plugin-server.plugininitializercontext.env.md) | <code>{</code><br/><code> mode: EnvironmentMode;</code><br/><code> }</code> | | | [env](./kibana-plugin-server.plugininitializercontext.env.md) | <code>{</code><br/><code> mode: EnvironmentMode;</code><br/><code> packageInfo: Readonly&lt;PackageInfo&gt;;</code><br/><code> }</code> | |
| [logger](./kibana-plugin-server.plugininitializercontext.logger.md) | <code>LoggerFactory</code> | | | [logger](./kibana-plugin-server.plugininitializercontext.logger.md) | <code>LoggerFactory</code> | |
| [opaqueId](./kibana-plugin-server.plugininitializercontext.opaqueid.md) | <code>PluginOpaqueId</code> | | | [opaqueId](./kibana-plugin-server.plugininitializercontext.opaqueid.md) | <code>PluginOpaqueId</code> | |

View file

@ -20,17 +20,18 @@
import { PluginOpaqueId } from '../../server'; import { PluginOpaqueId } from '../../server';
import { MockContextConstructor } from './context_service.test.mocks'; import { MockContextConstructor } from './context_service.test.mocks';
import { ContextService } from './context_service'; import { ContextService } from './context_service';
import { coreMock } from '../mocks';
const pluginDependencies = new Map<PluginOpaqueId, PluginOpaqueId[]>(); const pluginDependencies = new Map<PluginOpaqueId, PluginOpaqueId[]>();
describe('ContextService', () => { describe('ContextService', () => {
describe('#setup()', () => { describe('#setup()', () => {
test('createContextContainer returns a new container configured with pluginDependencies', () => { test('createContextContainer returns a new container configured with pluginDependencies', () => {
const coreId = Symbol(); const context = coreMock.createCoreContext();
const service = new ContextService({ coreId }); const service = new ContextService(context);
const setup = service.setup({ pluginDependencies }); const setup = service.setup({ pluginDependencies });
expect(setup.createContextContainer()).toBeDefined(); expect(setup.createContextContainer()).toBeDefined();
expect(MockContextConstructor).toHaveBeenCalledWith(pluginDependencies, coreId); expect(MockContextConstructor).toHaveBeenCalledWith(pluginDependencies, context.coreId);
}); });
}); });
}); });

View file

@ -20,6 +20,7 @@
import './core.css'; import './core.css';
import { CoreId } from '../server'; import { CoreId } from '../server';
import { PackageInfo, EnvironmentMode } from '../server/types';
import { CoreSetup, CoreStart } from '.'; import { CoreSetup, CoreStart } from '.';
import { ChromeService } from './chrome'; import { ChromeService } from './chrome';
import { FatalErrorsService, FatalErrorsSetup } from './fatal_errors'; import { FatalErrorsService, FatalErrorsSetup } from './fatal_errors';
@ -55,6 +56,10 @@ interface Params {
/** @internal */ /** @internal */
export interface CoreContext { export interface CoreContext {
coreId: CoreId; coreId: CoreId;
env: {
mode: Readonly<EnvironmentMode>;
packageInfo: Readonly<PackageInfo>;
};
} }
/** @internal */ /** @internal */
@ -130,7 +135,8 @@ export class CoreSystem {
this.rendering = new RenderingService(); this.rendering = new RenderingService();
this.application = new ApplicationService(); this.application = new ApplicationService();
this.coreContext = { coreId: Symbol('core') }; this.coreContext = { coreId: Symbol('core'), env: injectedMetadata.env };
this.context = new ContextService(this.coreContext); this.context = new ContextService(this.coreContext);
this.plugins = new PluginsService(this.coreContext, injectedMetadata.uiPlugins); this.plugins = new PluginsService(this.coreContext, injectedMetadata.uiPlugins);

View file

@ -67,6 +67,7 @@ import { UiSettingsClient, UiSettingsState, UiSettingsClientContract } from './u
import { ApplicationSetup, Capabilities, ApplicationStart } from './application'; import { ApplicationSetup, Capabilities, ApplicationStart } from './application';
import { DocLinksStart } from './doc_links'; import { DocLinksStart } from './doc_links';
import { SavedObjectsStart } from './saved_objects'; import { SavedObjectsStart } from './saved_objects';
export { PackageInfo, EnvironmentMode } from '../server/types';
import { import {
IContextContainer, IContextContainer,
IContextProvider, IContextProvider,

View file

@ -19,6 +19,7 @@
import { get } from 'lodash'; import { get } from 'lodash';
import { DiscoveredPlugin, PluginName } from '../../server'; import { DiscoveredPlugin, PluginName } from '../../server';
import { EnvironmentMode, PackageInfo } from '../../server/types';
import { UiSettingsState } from '../ui_settings'; import { UiSettingsState } from '../ui_settings';
import { deepFreeze } from '../../utils/'; import { deepFreeze } from '../../utils/';
import { Capabilities } from '..'; import { Capabilities } from '..';
@ -46,6 +47,10 @@ export interface InjectedMetadataParams {
vars: { vars: {
[key: string]: unknown; [key: string]: unknown;
}; };
env: {
mode: Readonly<EnvironmentMode>;
packageInfo: Readonly<PackageInfo>;
};
uiPlugins: Array<{ uiPlugins: Array<{
id: PluginName; id: PluginName;
plugin: DiscoveredPlugin; plugin: DiscoveredPlugin;

View file

@ -18,7 +18,7 @@
*/ */
import { applicationServiceMock } from './application/application_service.mock'; import { applicationServiceMock } from './application/application_service.mock';
import { chromeServiceMock } from './chrome/chrome_service.mock'; import { chromeServiceMock } from './chrome/chrome_service.mock';
import { CoreSetup, CoreStart, PluginInitializerContext } from '.'; import { CoreContext, CoreSetup, CoreStart, PluginInitializerContext } from '.';
import { docLinksServiceMock } from './doc_links/doc_links_service.mock'; import { docLinksServiceMock } from './doc_links/doc_links_service.mock';
import { fatalErrorsServiceMock } from './fatal_errors/fatal_errors_service.mock'; import { fatalErrorsServiceMock } from './fatal_errors/fatal_errors_service.mock';
import { httpServiceMock } from './http/http_service.mock'; import { httpServiceMock } from './http/http_service.mock';
@ -75,9 +75,51 @@ function createCoreStartMock() {
return mock; return mock;
} }
function pluginInitializerContextMock() {
const mock: PluginInitializerContext = {
opaqueId: Symbol(),
env: {
mode: {
dev: true,
name: 'development',
prod: false,
},
packageInfo: {
version: 'version',
branch: 'branch',
buildNum: 100,
buildSha: 'buildSha',
dist: false,
},
},
};
return mock;
}
function createCoreContext(): CoreContext {
return {
coreId: Symbol('core context mock'),
env: {
mode: {
dev: true,
name: 'development',
prod: false,
},
packageInfo: {
version: 'version',
branch: 'branch',
buildNum: 100,
buildSha: 'buildSha',
dist: false,
},
},
};
}
export const coreMock = { export const coreMock = {
createCoreContext,
createSetup: createCoreSetupMock, createSetup: createCoreSetupMock,
createStart: createCoreStartMock, createStart: createCoreStartMock,
createPluginInitializerContext: jest.fn() as jest.Mock<PluginInitializerContext>, createPluginInitializerContext: pluginInitializerContextMock,
}; };

View file

@ -19,6 +19,7 @@
import { mockInitializer, mockPlugin, mockPluginLoader } from './plugin.test.mocks'; import { mockInitializer, mockPlugin, mockPluginLoader } from './plugin.test.mocks';
import { DiscoveredPlugin } from '../../server'; import { DiscoveredPlugin } from '../../server';
import { coreMock } from '../mocks';
import { PluginWrapper } from './plugin'; import { PluginWrapper } from './plugin';
function createManifest( function createManifest(
@ -36,7 +37,7 @@ function createManifest(
let plugin: PluginWrapper<unknown, Record<string, unknown>>; let plugin: PluginWrapper<unknown, Record<string, unknown>>;
const opaqueId = Symbol(); const opaqueId = Symbol();
const initializerContext = { opaqueId }; const initializerContext = coreMock.createPluginInitializerContext();
const addBasePath = (path: string) => path; const addBasePath = (path: string) => path;
beforeEach(() => { beforeEach(() => {

View file

@ -19,7 +19,8 @@
import { omit } from 'lodash'; import { omit } from 'lodash';
import { DiscoveredPlugin, PluginOpaqueId } from '../../server'; import { DiscoveredPlugin } from '../../server';
import { PluginOpaqueId, PackageInfo, EnvironmentMode } from '../../server/types';
import { CoreContext } from '../core_system'; import { CoreContext } from '../core_system';
import { PluginWrapper } from './plugin'; import { PluginWrapper } from './plugin';
import { PluginsServiceSetupDeps, PluginsServiceStartDeps } from './plugins_service'; import { PluginsServiceSetupDeps, PluginsServiceStartDeps } from './plugins_service';
@ -35,6 +36,10 @@ export interface PluginInitializerContext {
* A symbol used to identify this plugin in the system. Needed when registering handlers or context providers. * A symbol used to identify this plugin in the system. Needed when registering handlers or context providers.
*/ */
readonly opaqueId: PluginOpaqueId; readonly opaqueId: PluginOpaqueId;
readonly env: {
mode: Readonly<EnvironmentMode>;
packageInfo: Readonly<PackageInfo>;
};
} }
/** /**
@ -52,6 +57,7 @@ export function createPluginInitializerContext(
): PluginInitializerContext { ): PluginInitializerContext {
return { return {
opaqueId, opaqueId,
env: coreContext.env,
}; };
} }

View file

@ -26,7 +26,7 @@ import {
} from './plugins_service.test.mocks'; } from './plugins_service.test.mocks';
import { PluginName, DiscoveredPlugin } from 'src/core/server'; import { PluginName, DiscoveredPlugin } from 'src/core/server';
import { CoreContext } from '../core_system'; import { coreMock } from '../mocks';
import { import {
PluginsService, PluginsService,
PluginsServiceStartDeps, PluginsServiceStartDeps,
@ -56,7 +56,7 @@ let plugins: Array<{ id: string; plugin: DiscoveredPlugin }>;
type DeeplyMocked<T> = { [P in keyof T]: jest.Mocked<T[P]> }; type DeeplyMocked<T> = { [P in keyof T]: jest.Mocked<T[P]> };
const mockCoreContext: CoreContext = { coreId: Symbol() }; const mockCoreContext = coreMock.createCoreContext();
let mockSetupDeps: DeeplyMocked<PluginsServiceSetupDeps>; let mockSetupDeps: DeeplyMocked<PluginsServiceSetupDeps>;
let mockSetupContext: DeeplyMocked<CoreSetup>; let mockSetupContext: DeeplyMocked<CoreSetup>;
let mockStartDeps: DeeplyMocked<PluginsServiceStartDeps>; let mockStartDeps: DeeplyMocked<PluginsServiceStartDeps>;

View file

@ -226,6 +226,11 @@ export interface CoreContext {
// //
// (undocumented) // (undocumented)
coreId: CoreId; coreId: CoreId;
// (undocumented)
env: {
mode: Readonly<EnvironmentMode>;
packageInfo: Readonly<PackageInfo>;
};
} }
// @public // @public
@ -379,6 +384,16 @@ export interface DocLinksStart {
}; };
} }
// @public (undocumented)
export interface EnvironmentMode {
// (undocumented)
dev: boolean;
// (undocumented)
name: 'development' | 'production';
// (undocumented)
prod: boolean;
}
// Warning: (ae-missing-release-tag) "ErrorToastOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // Warning: (ae-missing-release-tag) "ErrorToastOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// //
// @public (undocumented) // @public (undocumented)
@ -681,6 +696,20 @@ export interface OverlayStart {
}) => OverlayRef; }) => OverlayRef;
} }
// @public (undocumented)
export interface PackageInfo {
// (undocumented)
branch: string;
// (undocumented)
buildNum: number;
// (undocumented)
buildSha: string;
// (undocumented)
dist: boolean;
// (undocumented)
version: string;
}
// @public // @public
export interface Plugin<TSetup = void, TStart = void, TPluginsSetup extends object = object, TPluginsStart extends object = object> { export interface Plugin<TSetup = void, TStart = void, TPluginsSetup extends object = object, TPluginsStart extends object = object> {
// (undocumented) // (undocumented)
@ -696,6 +725,11 @@ export type PluginInitializer<TSetup, TStart, TPluginsSetup extends object = obj
// @public // @public
export interface PluginInitializerContext { export interface PluginInitializerContext {
// (undocumented)
readonly env: {
mode: Readonly<EnvironmentMode>;
packageInfo: Readonly<PackageInfo>;
};
readonly opaqueId: PluginOpaqueId; readonly opaqueId: PluginOpaqueId;
} }

View file

@ -18,25 +18,12 @@
*/ */
import { resolve, dirname } from 'path'; import { resolve, dirname } from 'path';
import { PackageInfo, EnvironmentMode } from './types';
// `require` is necessary for this to work inside x-pack code as well // `require` is necessary for this to work inside x-pack code as well
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires
const pkg = require('../../../../package.json'); const pkg = require('../../../../package.json');
export interface PackageInfo {
version: string;
branch: string;
buildNum: number;
buildSha: string;
dist: boolean;
}
export interface EnvironmentMode {
name: 'development' | 'production';
dev: boolean;
prod: boolean;
}
/** @internal */ /** @internal */
export interface EnvOptions { export interface EnvOptions {
configs: string[]; configs: string[];

View file

@ -21,6 +21,6 @@ export { ConfigService, IConfigService } from './config_service';
export { RawConfigService } from './raw_config_service'; export { RawConfigService } from './raw_config_service';
export { Config, ConfigPath, isConfigPath, hasConfigPathIntersection } from './config'; export { Config, ConfigPath, isConfigPath, hasConfigPathIntersection } from './config';
export { ObjectToConfigAdapter } from './object_to_config_adapter'; export { ObjectToConfigAdapter } from './object_to_config_adapter';
export { CliArgs } from './env'; export { CliArgs, Env } from './env';
export { Env, EnvironmentMode, PackageInfo } from './env'; export { EnvironmentMode, PackageInfo } from './types';

View file

@ -17,6 +17,22 @@
* under the License. * under the License.
*/ */
/** This module is intended for consumption by public to avoid import issues with server-side code */ /**
* @public
*/
export interface PackageInfo {
version: string;
branch: string;
buildNum: number;
buildSha: string;
dist: boolean;
}
export { PluginOpaqueId } from './plugins/types'; /**
* @public
*/
export interface EnvironmentMode {
name: 'development' | 'production';
dev: boolean;
prod: boolean;
}

View file

@ -58,7 +58,7 @@ import { ContextSetup } from './context';
import { SavedObjectsServiceStart } from './saved_objects'; import { SavedObjectsServiceStart } from './saved_objects';
export { bootstrap } from './bootstrap'; export { bootstrap } from './bootstrap';
export { ConfigPath, ConfigService } from './config'; export { ConfigPath, ConfigService, EnvironmentMode, PackageInfo } from './config';
export { export {
IContextContainer, IContextContainer,
IContextProvider, IContextProvider,

View file

@ -257,6 +257,10 @@ export class LegacyService implements CoreService<LegacyServiceSetup> {
settings, settings,
config, config,
{ {
env: {
mode: this.coreContext.env.mode,
packageInfo: this.coreContext.env.packageInfo,
},
handledConfigPaths: await this.coreContext.configService.getUsedPaths(), handledConfigPaths: await this.coreContext.configService.getUsedPaths(),
setupDeps: { setupDeps: {
core: coreSetup, core: coreSetup,

View file

@ -40,7 +40,7 @@ export function pluginInitializerContextConfigMock<T>(config: T) {
return mock; return mock;
} }
function pluginInitializerContextMock<T>(config: T) { function pluginInitializerContextMock<T>(config: T = {} as T) {
const mock: PluginInitializerContext<T> = { const mock: PluginInitializerContext<T> = {
opaqueId: Symbol(), opaqueId: Symbol(),
logger: loggingServiceMock.create(), logger: loggingServiceMock.create(),
@ -50,6 +50,13 @@ function pluginInitializerContextMock<T>(config: T) {
name: 'development', name: 'development',
prod: false, prod: false,
}, },
packageInfo: {
version: 'version',
branch: 'branch',
buildNum: 100,
buildSha: 'buildSha',
dist: false,
},
}, },
config: pluginInitializerContextConfigMock<T>(config), config: pluginInitializerContextConfigMock<T>(config),
}; };

View file

@ -47,7 +47,10 @@ export function createPluginInitializerContext(
/** /**
* Environment information that is safe to expose to plugins and may be beneficial for them. * Environment information that is safe to expose to plugins and may be beneficial for them.
*/ */
env: { mode: coreContext.env.mode }, env: {
mode: coreContext.env.mode,
packageInfo: coreContext.env.packageInfo,
},
/** /**
* Plugin-scoped logger * Plugin-scoped logger

View file

@ -20,7 +20,7 @@
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { Type } from '@kbn/config-schema'; import { Type } from '@kbn/config-schema';
import { ConfigPath, EnvironmentMode } from '../config'; import { ConfigPath, EnvironmentMode, PackageInfo } from '../config';
import { LoggerFactory } from '../logging'; import { LoggerFactory } from '../logging';
import { CoreSetup, CoreStart } from '..'; import { CoreSetup, CoreStart } from '..';
@ -159,7 +159,10 @@ export interface Plugin<
*/ */
export interface PluginInitializerContext<ConfigSchema = unknown> { export interface PluginInitializerContext<ConfigSchema = unknown> {
opaqueId: PluginOpaqueId; opaqueId: PluginOpaqueId;
env: { mode: EnvironmentMode }; env: {
mode: EnvironmentMode;
packageInfo: Readonly<PackageInfo>;
};
logger: LoggerFactory; logger: LoggerFactory;
config: { config: {
create: <T = ConfigSchema>() => Observable<T>; create: <T = ConfigSchema>() => Observable<T>;

View file

@ -618,6 +618,16 @@ export interface ElasticsearchServiceSetup {
}; };
} }
// @public (undocumented)
export interface EnvironmentMode {
// (undocumented)
dev: boolean;
// (undocumented)
name: 'development' | 'production';
// (undocumented)
prod: boolean;
}
// @public // @public
export interface ErrorHttpResponseOptions { export interface ErrorHttpResponseOptions {
body?: ResponseError; body?: ResponseError;
@ -957,6 +967,20 @@ export interface OnPreAuthToolkit {
rewriteUrl: (url: string) => OnPreAuthResult; rewriteUrl: (url: string) => OnPreAuthResult;
} }
// @public (undocumented)
export interface PackageInfo {
// (undocumented)
branch: string;
// (undocumented)
buildNum: number;
// (undocumented)
buildSha: string;
// (undocumented)
dist: boolean;
// (undocumented)
version: string;
}
// @public // @public
export interface Plugin<TSetup = void, TStart = void, TPluginsSetup extends object = object, TPluginsStart extends object = object> { export interface Plugin<TSetup = void, TStart = void, TPluginsSetup extends object = object, TPluginsStart extends object = object> {
// (undocumented) // (undocumented)
@ -980,6 +1004,7 @@ export interface PluginInitializerContext<ConfigSchema = unknown> {
// (undocumented) // (undocumented)
env: { env: {
mode: EnvironmentMode; mode: EnvironmentMode;
packageInfo: Readonly<PackageInfo>;
}; };
// (undocumented) // (undocumented)
logger: LoggerFactory; logger: LoggerFactory;
@ -1553,6 +1578,5 @@ export interface SessionStorageFactory<T> {
// Warnings were encountered during analysis: // Warnings were encountered during analysis:
// //
// src/core/server/plugins/plugins_service.ts:39:5 - (ae-forgotten-export) The symbol "DiscoveredPluginInternal" needs to be exported by the entry point index.d.ts // src/core/server/plugins/plugins_service.ts:39:5 - (ae-forgotten-export) The symbol "DiscoveredPluginInternal" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:162:10 - (ae-forgotten-export) The symbol "EnvironmentMode" needs to be exported by the entry point index.d.ts
``` ```

View file

@ -20,3 +20,4 @@
/** This module is intended for consumption by public to avoid import issues with server-side code */ /** This module is intended for consumption by public to avoid import issues with server-side code */
export { PluginOpaqueId } from './plugins/types'; export { PluginOpaqueId } from './plugins/types';
export * from './saved_objects/types'; export * from './saved_objects/types';
export { EnvironmentMode, PackageInfo } from './config/types';

View file

@ -24,9 +24,11 @@ import { SavedObjectsClientProviderOptions, CoreSetup } from 'src/core/server';
import { import {
ConfigService, ConfigService,
ElasticsearchServiceSetup, ElasticsearchServiceSetup,
EnvironmentMode,
LoggerFactory, LoggerFactory,
SavedObjectsClientContract, SavedObjectsClientContract,
SavedObjectsLegacyService, SavedObjectsLegacyService,
PackageInfo,
} from '../../core/server'; } from '../../core/server';
import { LegacyServiceSetupDeps, LegacyServiceStartDeps } from '../../core/server/'; import { LegacyServiceSetupDeps, LegacyServiceStartDeps } from '../../core/server/';
@ -102,6 +104,10 @@ type KbnMixinFunc = (kbnServer: KbnServer, server: Server, config: any) => Promi
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
export default class KbnServer { export default class KbnServer {
public readonly newPlatform: { public readonly newPlatform: {
env: {
mode: Readonly<EnvironmentMode>;
packageInfo: Readonly<PackageInfo>;
};
coreContext: { coreContext: {
logger: LoggerFactory; logger: LoggerFactory;
}; };

View file

@ -57,10 +57,14 @@ export default class KbnServer {
this.settings = settings || {}; this.settings = settings || {};
this.config = config; this.config = config;
const { setupDeps, startDeps, handledConfigPaths, logger, __internals } = core; const { setupDeps, startDeps, handledConfigPaths, logger, __internals, env } = core;
this.server = __internals.hapiServer; this.server = __internals.hapiServer;
this.newPlatform = { this.newPlatform = {
env: {
mode: env.mode,
packageInfo: env.packageInfo,
},
__internals, __internals,
coreContext: { coreContext: {
logger, logger,

View file

@ -237,6 +237,7 @@ export function uiRenderMixin(kbnServer, server, config) {
buildNumber: config.get('pkg.buildNum'), buildNumber: config.get('pkg.buildNum'),
branch: config.get('pkg.branch'), branch: config.get('pkg.branch'),
basePath, basePath,
env: kbnServer.newPlatform.env,
legacyMode: app.getId() !== 'core', legacyMode: app.getId() !== 'core',
i18n: { i18n: {
translationsUrl: `${basePath}/translations/${i18n.getLocale()}.json`, translationsUrl: `${basePath}/translations/${i18n.getLocale()}.json`,

View file

@ -25,10 +25,9 @@ import { searchSetupMock } from '../mocks';
describe('ES search strategy service', () => { describe('ES search strategy service', () => {
let service: EsSearchService; let service: EsSearchService;
let mockCoreSetup: MockedKeys<CoreSetup>; let mockCoreSetup: MockedKeys<CoreSetup>;
const opaqueId = Symbol();
beforeEach(() => { beforeEach(() => {
service = new EsSearchService({ opaqueId }); service = new EsSearchService(coreMock.createPluginInitializerContext());
mockCoreSetup = coreMock.createSetup(); mockCoreSetup = coreMock.createSetup();
}); });

View file

@ -16,10 +16,10 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
import { coreMock } from '../../../../../../src/core/public/mocks';
import { esSearchService } from '.'; import { esSearchService } from '.';
it('es search service is instantiated', () => { it('es search service is instantiated', () => {
const esSearch = esSearchService({ opaqueId: Symbol() }); const esSearch = esSearchService(coreMock.createPluginInitializerContext());
expect(esSearch).toBeDefined(); expect(esSearch).toBeDefined();
}); });

View file

@ -25,9 +25,9 @@ import { CoreSetup } from '../../../../core/public';
describe('Search service', () => { describe('Search service', () => {
let searchService: SearchService; let searchService: SearchService;
let mockCoreSetup: MockedKeys<CoreSetup>; let mockCoreSetup: MockedKeys<CoreSetup>;
const opaqueId = Symbol();
beforeEach(() => { beforeEach(() => {
searchService = new SearchService({ opaqueId }); searchService = new SearchService(coreMock.createPluginInitializerContext());
mockCoreSetup = coreMock.createSetup(); mockCoreSetup = coreMock.createSetup();
}); });

View file

@ -19,31 +19,13 @@
import { coreMock } from '../../../../../core/server/mocks'; import { coreMock } from '../../../../../core/server/mocks';
import { EsSearchService } from './es_search_service'; import { EsSearchService } from './es_search_service';
import { PluginInitializerContext } from '../../../../../core/server';
import { searchSetupMock } from '../mocks'; import { searchSetupMock } from '../mocks';
describe('ES search strategy service', () => { describe('ES search strategy service', () => {
let service: EsSearchService; let service: EsSearchService;
const mockCoreSetup = coreMock.createSetup(); const mockCoreSetup = coreMock.createSetup();
const opaqueId = Symbol(); const context = coreMock.createPluginInitializerContext();
const context: PluginInitializerContext = {
opaqueId,
config: {
createIfExists: jest.fn(),
create: jest.fn(),
},
env: {
mode: {
dev: false,
name: 'development',
prod: false,
},
},
logger: {
get: jest.fn(),
},
};
beforeEach(() => { beforeEach(() => {
service = new EsSearchService(context); service = new EsSearchService(context);

View file

@ -17,7 +17,7 @@
* under the License. * under the License.
*/ */
import { PluginInitializer } from 'kibana/public'; import { PluginInitializer, PluginInitializerContext } from 'kibana/public';
import { import {
CorePluginBDeps, CorePluginBDeps,
CorePluginBPlugin, CorePluginBPlugin,
@ -29,4 +29,4 @@ export const plugin: PluginInitializer<
CorePluginBPluginSetup, CorePluginBPluginSetup,
CorePluginBPluginStart, CorePluginBPluginStart,
CorePluginBDeps CorePluginBDeps
> = () => new CorePluginBPlugin(); > = (context: PluginInitializerContext) => new CorePluginBPlugin(context);

View file

@ -17,13 +17,14 @@
* under the License. * under the License.
*/ */
import { Plugin, CoreSetup } from 'kibana/public'; import { CoreSetup, Plugin, PluginInitializerContext } from 'kibana/public';
import { CorePluginAPluginSetup } from '../../core_plugin_a/public/plugin'; import { CorePluginAPluginSetup } from '../../core_plugin_a/public/plugin';
declare global { declare global {
interface Window { interface Window {
corePluginB?: string; corePluginB?: string;
hasAccessToInjectedMetadata?: boolean; hasAccessToInjectedMetadata?: boolean;
env?: PluginInitializerContext['env'];
} }
} }
@ -33,6 +34,9 @@ export interface CorePluginBDeps {
export class CorePluginBPlugin export class CorePluginBPlugin
implements Plugin<CorePluginBPluginSetup, CorePluginBPluginStart, CorePluginBDeps> { implements Plugin<CorePluginBPluginSetup, CorePluginBPluginStart, CorePluginBDeps> {
constructor(pluginContext: PluginInitializerContext) {
window.env = pluginContext.env;
}
public setup(core: CoreSetup, deps: CorePluginBDeps) { public setup(core: CoreSetup, deps: CorePluginBDeps) {
window.corePluginB = `Plugin A said: ${deps.core_plugin_a.getGreeting()}`; window.corePluginB = `Plugin A said: ${deps.core_plugin_a.getGreeting()}`;
window.hasAccessToInjectedMetadata = 'getInjectedVar' in core.injectedMetadata; window.hasAccessToInjectedMetadata = 'getInjectedVar' in core.injectedMetadata;

View file

@ -44,5 +44,16 @@ export default function ({ getService, getPageObjects }) {
expect(hasAccessToInjectedMetadata).to.equal(true); 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 () => {
const envData = await browser.execute('return window.env');
expect(envData.mode.dev).to.be(true);
expect(envData.packageInfo.version).to.be.a('string');
});
});
}); });
} }

View file

@ -8,4 +8,4 @@ import chrome from 'ui/chrome';
import { npStart } from 'ui/new_platform'; import { npStart } from 'ui/new_platform';
import { Plugin } from './plugin'; import { Plugin } from './plugin';
new Plugin({ opaqueId: Symbol('uptime') }, chrome).start(npStart); new Plugin({ opaqueId: Symbol('uptime'), env: {} as any }, chrome).start(npStart);