Serve static assets from NP (#60490)

* add hapi.inert plugin to NP

* update tests

* move serving static assets

* update tests

* add functional tests

* fix type errors. Hapi.Request doesn't support typings for payload

* update docs

* remove comment

* move assets to NP

* update all assets references

* address Spencer's comments

* move ui settings migration to migration examples

* document legacy plugin spec

* move platform assets test to integration_tests

* address Spencer's comment p.2

* try to fix type errors

* fix merge commit

* update tests
This commit is contained in:
Mikhail Shustov 2020-03-27 14:24:28 +01:00 committed by GitHub
parent 01451212f2
commit ab39ceba8f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
128 changed files with 419 additions and 187 deletions

View file

@ -65,7 +65,7 @@
"uiFramework:documentComponent": "cd packages/kbn-ui-framework && yarn documentComponent",
"kbn:watch": "node scripts/kibana --dev --logging.json=false",
"build:types": "tsc --p tsconfig.types.json",
"docs:acceptApiChanges": "node scripts/check_published_api_changes.js --accept",
"docs:acceptApiChanges": "node --max-old-space-size=6144 scripts/check_published_api_changes.js --accept",
"kbn:bootstrap": "yarn build:types && node scripts/register_git_hook",
"spec_to_console": "node scripts/spec_to_console",
"backport-skip-ci": "backport --prDescription \"[skip-ci]\"",
@ -330,11 +330,13 @@
"@types/glob": "^7.1.1",
"@types/globby": "^8.0.0",
"@types/graphql": "^0.13.2",
"@types/h2o2": "^8.1.1",
"@types/hapi": "^17.0.18",
"@types/hapi-auth-cookie": "^9.1.0",
"@types/has-ansi": "^3.0.0",
"@types/history": "^4.7.3",
"@types/hoek": "^4.1.3",
"@types/inert": "^5.1.2",
"@types/jest": "24.0.19",
"@types/joi": "^13.4.2",
"@types/jquery": "^3.3.31",

View file

@ -131,12 +131,21 @@ export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) {
loader: 'resolve-url-loader',
options: {
join: (_: string, __: any) => (uri: string, base?: string) => {
if (!base) {
// apply only to legacy platform styles
if (!base || !parseDirPath(base).dirs.includes('legacy')) {
return null;
}
if (uri.startsWith('ui/assets')) {
return Path.resolve(
worker.repoRoot,
'src/core/server/core_app/',
uri.replace('ui/', '')
);
}
// manually force ui/* urls in legacy styles to resolve to ui/legacy/public
if (uri.startsWith('ui/') && parseDirPath(base).dirs.includes('legacy')) {
if (uri.startsWith('ui/')) {
return Path.resolve(
worker.repoRoot,
'src/legacy/ui/public',

View file

@ -22,5 +22,5 @@ const path = require('path');
// Extend the Storybook Middleware to include a route to access Legacy UI assets
module.exports = function(router) {
router.get('/ui', serve(path.resolve(__dirname, '../../../../src/legacy/ui/public/assets')));
router.get('/ui', serve(path.resolve(__dirname, '../../../src/core/server/core_app/assets')));
};

View file

@ -43,6 +43,7 @@
- [Core services](#core-services-1)
- [Plugin services](#plugin-services)
- [UI Exports](#ui-exports)
- [Plugin Spec](#plugin-spec)
- [How to](#how-to)
- [Configure plugin](#configure-plugin)
- [Handle plugin configuration deprecations](#handle-plugin-configuration-deprecations)
@ -1264,40 +1265,19 @@ This table shows where these uiExports have moved to in the New Platform. In mos
| `visTypes` | `plugins.visualizations.types` | |
| `visualize` | | |
Examples:
- **uiSettingDefaults**
Before:
```js
uiExports: {
uiSettingDefaults: {
'my-plugin:my-setting': {
name: 'just-work',
value: true,
description: 'make it work',
category: ['my-category'],
},
}
}
```
After:
```ts
// src/plugins/my-plugin/server/plugin.ts
setup(core: CoreSetup){
core.uiSettings.register({
'my-plugin:my-setting': {
name: 'just-work',
value: true,
description: 'make it work',
category: ['my-category'],
},
})
}
```
#### Plugin Spec
| Legacy Platform | New Platform |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `id` | [`manifest.id`](/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) |
| `require` | [`manifest.requiredPlugins`](/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) |
| `version` | [`manifest.version`](/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) |
| `kibanaVersion` | [`manifest.kibanaVersion`](/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) |
| `configPrefix` | [`manifest.configPath`](/docs/development/core/server/kibana-plugin-core-server.pluginmanifest.md) |
| `config` | [export config](#configure-plugin) |
| `deprecations` | [export config](#handle-plugin-configuration-deprecations) |
| `uiExports` | `N/A`. Use platform & plugin public contracts |
| `publicDir` | `N/A`. Platform serves static assets from `/public/assets` folder under `/plugins/{id}/assets/{path*}` URL. |
| `preInit`, `init`, `postInit` | `N/A`. Use NP [lifecycle events](#services) |
## How to

View file

@ -20,6 +20,7 @@ APIs to their New Platform equivalents.
- [Chromeless Applications](#chromeless-applications)
- [Render HTML Content](#render-html-content)
- [Saved Objects types](#saved-objects-types)
- [UiSettings](#uisettings)
## Configuration
@ -975,4 +976,37 @@ const migration: SavedObjectMigrationFn = (doc, { log }) => {...}
The `registerType` API will throw if called after the service has started, and therefor cannot be used from
legacy plugin code. Legacy plugins should use the legacy savedObjects service and the legacy way to register
saved object types until migrated.
saved object types until migrated.
## UiSettings
UiSettings defaults registration performed during `setup` phase via `core.uiSettings.register` API.
```js
// Before:
uiExports: {
uiSettingDefaults: {
'my-plugin:my-setting': {
name: 'just-work',
value: true,
description: 'make it work',
category: ['my-category'],
},
}
}
```
```ts
// After:
// src/plugins/my-plugin/server/plugin.ts
setup(core: CoreSetup){
core.uiSettings.register({
'my-plugin:my-setting': {
name: 'just-work',
value: true,
description: 'make it work',
category: ['my-category'],
schema: schema.boolean(),
},
})
}
```

View file

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 9 KiB

After

Width:  |  Height:  |  Size: 9 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 773 B

After

Width:  |  Height:  |  Size: 773 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Before After
Before After

View file

@ -16,6 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
import Path from 'path';
import { fromRoot } from '../../../core/server/utils';
import { InternalCoreSetup } from '../internal_types';
import { CoreContext } from '../core_context';
import { Logger } from '../logging';
@ -29,6 +32,7 @@ export class CoreApp {
setup(coreSetup: InternalCoreSetup) {
this.logger.debug('Setting up core app.');
this.registerDefaultRoutes(coreSetup);
this.registerStaticDirs(coreSetup);
}
private registerDefaultRoutes(coreSetup: InternalCoreSetup) {
@ -49,4 +53,12 @@ export class CoreApp {
res.ok({ body: { version: '0.0.1' } })
);
}
private registerStaticDirs(coreSetup: InternalCoreSetup) {
coreSetup.http.registerStaticDir('/ui/{path*}', Path.resolve(__dirname, './assets'));
coreSetup.http.registerStaticDir(
'/node_modules/@kbn/ui-framework/dist/{path*}',
fromRoot('node_modules/@kbn/ui-framework/dist')
);
}
}

View file

@ -0,0 +1,51 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import * as kbnTestServer from '../../../../test_utils/kbn_server';
import { Root } from '../../root';
describe('Platform assets', function() {
let root: Root;
beforeAll(async function() {
root = kbnTestServer.createRoot();
await root.setup();
await root.start();
});
afterAll(async function() {
await root.shutdown();
});
it('exposes static assets', async () => {
await kbnTestServer.request.get(root, '/ui/favicons/favicon.ico').expect(200);
});
it('returns 404 if not found', async function() {
await kbnTestServer.request.get(root, '/ui/favicons/not-a-favicon.ico').expect(404);
});
it('does not expose folder content', async function() {
await kbnTestServer.request.get(root, '/ui/favicons/').expect(403);
});
it('does not allow file tree traversing', async function() {
await kbnTestServer.request.get(root, '/ui/../../../../../README.md').expect(404);
});
});

View file

@ -23,6 +23,7 @@ import { Agent as HttpsAgent, ServerOptions as TlsOptions } from 'https';
import apm from 'elastic-apm-node';
import { ByteSizeValue } from '@kbn/config-schema';
import { Server, Request, ResponseToolkit } from 'hapi';
import HapiProxy from 'h2o2';
import { sample } from 'lodash';
import BrowserslistUserAgent from 'browserslist-useragent';
import * as Rx from 'rxjs';
@ -102,7 +103,7 @@ export class BasePathProxyServer {
// Register hapi plugin that adds proxying functionality. It can be configured
// through the route configuration object (see { handler: { proxy: ... } }).
await this.server.register({ plugin: require('h2o2') });
await this.server.register([HapiProxy]);
if (this.httpConfig.ssl.enabled) {
const tlsOptions = serverOptions.tls as TlsOptions;
@ -166,7 +167,8 @@ export class BasePathProxyServer {
host: this.server.info.host,
passThrough: true,
port: this.devConfig.basePathProxyTargetPort,
protocol: this.server.info.protocol,
// typings mismatch. h2o2 doesn't support "socket"
protocol: this.server.info.protocol as HapiProxy.ProxyHandlerOptions['protocol'],
xforward: true,
},
},
@ -195,7 +197,7 @@ export class BasePathProxyServer {
agent: this.httpsAgent,
passThrough: true,
xforward: true,
mapUri: (request: Request) => ({
mapUri: async (request: Request) => ({
uri: Url.format({
hostname: request.server.info.host,
port: this.devConfig.basePathProxyTargetPort,

View file

@ -17,6 +17,7 @@
* under the License.
*/
import { Server } from 'hapi';
import HapiStaticFiles from 'inert';
import url from 'url';
import { Logger, LoggerFactory } from '../logging';
@ -44,6 +45,7 @@ export interface HttpServerSetup {
* @param router {@link IRouter} - a router with registered route handlers.
*/
registerRouter: (router: IRouter) => void;
registerStaticDir: (path: string, dirPath: string) => void;
basePath: HttpServiceSetup['basePath'];
csp: HttpServiceSetup['csp'];
createCookieSessionStorageFactory: HttpServiceSetup['createCookieSessionStorageFactory'];
@ -97,10 +99,11 @@ export class HttpServer {
this.registeredRouters.add(router);
}
public setup(config: HttpConfig): HttpServerSetup {
public async setup(config: HttpConfig): Promise<HttpServerSetup> {
const serverOptions = getServerOptions(config);
const listenerOptions = getListenerOptions(config);
this.server = createServer(serverOptions, listenerOptions);
await this.server.register([HapiStaticFiles]);
this.config = config;
const basePathService = new BasePath(config.basePath);
@ -109,6 +112,7 @@ export class HttpServer {
return {
registerRouter: this.registerRouter.bind(this),
registerStaticDir: this.registerStaticDir.bind(this),
registerOnPreAuth: this.registerOnPreAuth.bind(this),
registerOnPostAuth: this.registerOnPostAuth.bind(this),
registerOnPreResponse: this.registerOnPreResponse.bind(this),
@ -339,4 +343,23 @@ export class HttpServer {
return t.next({ headers: authResponseHeaders });
});
}
private registerStaticDir(path: string, dirPath: string) {
if (this.server === undefined) {
throw new Error('Http server is not setup up yet');
}
this.server.route({
path,
method: 'GET',
handler: {
directory: {
path: dirPath,
listing: false,
lookupCompressed: true,
},
},
options: { auth: false },
});
}
}

View file

@ -72,6 +72,7 @@ const createSetupContractMock = () => {
registerRouteHandlerContext: jest.fn(),
registerOnPreResponse: jest.fn(),
createRouter: jest.fn().mockImplementation(() => mockRouter.create({})),
registerStaticDir: jest.fn(),
basePath: createBasePathMock(),
csp: CspConfig.DEFAULT,
auth: createAuthMock(),

View file

@ -18,6 +18,8 @@
*/
jest.mock('fs', () => ({
// Hapi Inert patches native methods
...jest.requireActual('fs'),
readFileSync: jest.fn(),
}));

View file

@ -265,6 +265,7 @@ export interface InternalHttpServiceSetup
auth: HttpServerSetup['auth'];
server: HttpServerSetup['server'];
createRouter: (path: string, plugin?: PluginOpaqueId) => IRouter;
registerStaticDir: (path: string, dirPath: string) => void;
getAuthHeaders: GetAuthHeaders;
registerRouteHandlerContext: <T extends keyof RequestHandlerContext>(
pluginOpaqueId: PluginOpaqueId,

View file

@ -91,7 +91,15 @@ beforeEach(() => {
contracts: new Map([['plugin-id', 'plugin-value']]),
uiPlugins: {
public: new Map([['plugin-id', {} as DiscoveredPlugin]]),
internal: new Map([['plugin-id', { publicTargetDir: 'path/to/target/public' }]]),
internal: new Map([
[
'plugin-id',
{
publicTargetDir: 'path/to/target/public',
publicAssetsDir: '/plugins/name/assets/',
},
],
]),
browserConfigs: new Map(),
},
},

View file

@ -334,6 +334,9 @@ export class LegacyService implements CoreService {
plugins: startDeps.plugins,
},
__internals: {
http: {
registerStaticDir: setupDeps.core.http.registerStaticDir,
},
hapiServer: setupDeps.core.http.server,
kibanaMigrator: startDeps.core.savedObjects.migrator,
uiPlugins: setupDeps.core.plugins.uiPlugins,

View file

@ -540,13 +540,15 @@ describe('PluginsService', () => {
it('includes disabled plugins', async () => {
config$.next({ plugins: { initialize: true }, plugin1: { enabled: false } });
await pluginsService.discover();
const { uiPlugins } = await pluginsService.setup({} as any);
const { uiPlugins } = await pluginsService.setup(setupDeps);
expect(uiPlugins.internal).toMatchInlineSnapshot(`
Map {
"plugin-1" => Object {
"publicAssetsDir": <absolute path>/path-1/public/assets,
"publicTargetDir": <absolute path>/path-1/target/public,
},
"plugin-2" => Object {
"publicAssetsDir": <absolute path>/path-2/public/assets,
"publicTargetDir": <absolute path>/path-2/target/public,
},
}
@ -558,7 +560,7 @@ describe('PluginsService', () => {
it('does initialize if plugins.initialize is true', async () => {
config$.next({ plugins: { initialize: true } });
await pluginsService.discover();
const { initialized } = await pluginsService.setup({} as any);
const { initialized } = await pluginsService.setup(setupDeps);
expect(mockPluginSystem.setupPlugins).toHaveBeenCalled();
expect(initialized).toBe(true);
});
@ -566,7 +568,7 @@ describe('PluginsService', () => {
it('does not initialize if plugins.initialize is false', async () => {
config$.next({ plugins: { initialize: false } });
await pluginsService.discover();
const { initialized } = await pluginsService.setup({} as any);
const { initialized } = await pluginsService.setup(setupDeps);
expect(mockPluginSystem.setupPlugins).not.toHaveBeenCalled();
expect(initialized).toBe(false);
});

View file

@ -110,6 +110,7 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
const initialize = config.initialize && !this.coreContext.env.isDevClusterMaster;
if (initialize) {
contracts = await this.pluginsSystem.setupPlugins(deps);
this.registerPluginStaticDirs(deps);
} else {
this.log.info('Plugin initialization disabled.');
}
@ -223,6 +224,7 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
if (plugin.includesUiPlugin) {
this.uiPluginInternalInfo.set(plugin.name, {
publicTargetDir: Path.resolve(plugin.path, 'target/public'),
publicAssetsDir: Path.resolve(plugin.path, 'public/assets'),
});
}
@ -262,4 +264,13 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
)
);
}
private registerPluginStaticDirs(deps: PluginsServiceSetupDeps) {
for (const [pluginName, pluginInfo] of this.uiPluginInternalInfo) {
deps.http.registerStaticDir(
`/plugins/${pluginName}/assets/{path*}`,
pluginInfo.publicAssetsDir
);
}
}
}

View file

@ -194,6 +194,10 @@ export interface InternalPluginInfo {
* served
*/
readonly publicTargetDir: string;
/**
* Path to the plugin assets directory.
*/
readonly publicAssetsDir: string;
}
/**

View file

@ -2350,8 +2350,8 @@ export const validBodyOutput: readonly ["data", "stream"];
// src/core/server/legacy/types.ts:165:3 - (ae-forgotten-export) The symbol "LegacyAppSpec" needs to be exported by the entry point index.d.ts
// src/core/server/legacy/types.ts:166:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/plugins_service.ts:47:5 - (ae-forgotten-export) The symbol "InternalPluginInfo" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:226:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:226:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:228:3 - (ae-forgotten-export) The symbol "PathConfigType" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:230:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:230:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:232:3 - (ae-forgotten-export) The symbol "PathConfigType" needs to be exported by the entry point index.d.ts
```

View file

@ -41,7 +41,7 @@ export const IGNORE_FILE_GLOBS = [
'**/.*',
'**/{webpackShims,__mocks__}/**/*',
'x-pack/docs/**/*',
'src/legacy/ui/public/assets/fonts/**/*',
'src/core/server/core_app/assets/fonts/**/*',
'packages/kbn-utility-types/test-d/**/*',
'**/Jenkinsfile*',
'Dockerfile*',
@ -123,18 +123,18 @@ export const TEMPORARILY_IGNORED_PATHS = [
'src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/tlConfig.js',
'src/fixtures/config_upgrade_from_4.0.0_to_4.0.1-snapshot.json',
'src/legacy/core_plugins/vis_type_vislib/public/vislib/__tests__/lib/fixtures/mock_data/terms/_seriesMultiple.js',
'src/legacy/ui/public/assets/favicons/android-chrome-192x192.png',
'src/legacy/ui/public/assets/favicons/android-chrome-256x256.png',
'src/legacy/ui/public/assets/favicons/android-chrome-512x512.png',
'src/legacy/ui/public/assets/favicons/apple-touch-icon.png',
'src/legacy/ui/public/assets/favicons/favicon-16x16.png',
'src/legacy/ui/public/assets/favicons/favicon-32x32.png',
'src/legacy/ui/public/assets/favicons/mstile-70x70.png',
'src/legacy/ui/public/assets/favicons/mstile-144x144.png',
'src/legacy/ui/public/assets/favicons/mstile-150x150.png',
'src/legacy/ui/public/assets/favicons/mstile-310x150.png',
'src/legacy/ui/public/assets/favicons/mstile-310x310.png',
'src/legacy/ui/public/assets/favicons/safari-pinned-tab.svg',
'src/core/server/core_app/assets/favicons/android-chrome-192x192.png',
'src/core/server/core_app/assets/favicons/android-chrome-256x256.png',
'src/core/server/core_app/assets/favicons/android-chrome-512x512.png',
'src/core/server/core_app/assets/favicons/apple-touch-icon.png',
'src/core/server/core_app/assets/favicons/favicon-16x16.png',
'src/core/server/core_app/assets/favicons/favicon-32x32.png',
'src/core/server/core_app/assets/favicons/mstile-70x70.png',
'src/core/server/core_app/assets/favicons/mstile-144x144.png',
'src/core/server/core_app/assets/favicons/mstile-150x150.png',
'src/core/server/core_app/assets/favicons/mstile-310x150.png',
'src/core/server/core_app/assets/favicons/mstile-310x310.png',
'src/core/server/core_app/assets/favicons/safari-pinned-tab.svg',
'src/legacy/ui/public/styles/bootstrap/component-animations.less',
'src/legacy/ui/public/styles/bootstrap/input-groups.less',
'src/legacy/ui/public/styles/bootstrap/list-group.less',

View file

@ -18,7 +18,6 @@
*/
import { format } from 'url';
import { resolve } from 'path';
import _ from 'lodash';
import Boom from 'boom';
@ -32,22 +31,6 @@ export default async function(kbnServer, server, config) {
await registerHapiPlugins(server);
// provide a simple way to expose static directories
server.decorate('server', 'exposeStaticDir', function(routePath, dirPath) {
this.route({
path: routePath,
method: 'GET',
handler: {
directory: {
path: dirPath,
listing: false,
lookupCompressed: true,
},
},
config: { auth: false },
});
});
// helper for creating view managers for servers
server.decorate('server', 'setupViews', function(path, engines) {
this.views({
@ -77,7 +60,4 @@ export default async function(kbnServer, server, config) {
.permanent(true);
},
});
// Expose static assets
server.exposeStaticDir('/ui/{path*}', resolve(__dirname, '../../ui/public/assets'));
}

View file

@ -73,7 +73,10 @@ export class Plugin {
});
if (this.publicDir) {
server.exposeStaticDir(`/plugins/${id}/{path*}`, this.publicDir);
server.newPlatform.__internals.http.registerStaticDir(
`/plugins/${id}/{path*}`,
this.publicDir
);
}
// Many of the plugins are simply adding static assets to the server and we don't need

View file

@ -34,7 +34,7 @@ const access = promisify(fs.access);
const copyFile = promisify(fs.copyFile);
const mkdirAsync = promisify(fs.mkdir);
const UI_ASSETS_DIR = resolve(__dirname, '../../ui/public/assets');
const UI_ASSETS_DIR = resolve(__dirname, '../../../core/server/core_app/assets');
const DARK_THEME_IMPORTER = url => {
if (url.includes('eui_colors_light')) {
return { file: url.replace('eui_colors_light', 'eui_colors_dark') };

View file

@ -23,8 +23,6 @@ import { resolve } from 'path';
import { i18n } from '@kbn/i18n';
import * as UiSharedDeps from '@kbn/ui-shared-deps';
import { AppBootstrap } from './bootstrap';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { fromRoot } from '../../../core/server/utils';
import { getApmConfig } from '../apm';
import { DllCompiler } from '../../../optimize/dynamic_dll_plugin';
@ -43,11 +41,6 @@ export function uiRenderMixin(kbnServer, server, config) {
// render all views from ./views
server.setupViews(resolve(__dirname, 'views'));
server.exposeStaticDir(
'/node_modules/@kbn/ui-framework/dist/{path*}',
fromRoot('node_modules/@kbn/ui-framework/dist')
);
const translationsCache = { translations: null, hash: null };
server.route({
path: '/translations/{locale}.json',

View file

@ -16,18 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
import { FtrProviderContext } from 'test/functional/ftr_provider_context';
import { format as formatUrl } from 'url';
import supertestAsPromised from 'supertest-as-promised';
export function KibanaSupertestProvider({ getService }) {
export function KibanaSupertestProvider({ getService }: FtrProviderContext) {
const config = getService('config');
const kibanaServerUrl = formatUrl(config.get('servers.kibana'));
return supertestAsPromised(kibanaServerUrl);
}
export function ElasticsearchSupertestProvider({ getService }) {
export function ElasticsearchSupertestProvider({ getService }: FtrProviderContext) {
const config = getService('config');
const elasticSearchServerUrl = formatUrl(config.get('servers.elasticsearch'));
return supertestAsPromised(elasticSearchServerUrl);

View file

@ -44,7 +44,7 @@ export async function initPlugin(server: Hapi.Server, path: string) {
],
},
},
handler: newsfeedHandler,
handler: newsfeedHandler as Hapi.Lifecycle.Method,
});
server.route({

View file

@ -0,0 +1,7 @@
{
"id": "corePluginStaticAssets",
"version": "0.0.1",
"kibanaVersion": "kibana",
"server": false,
"ui": true
}

View file

@ -0,0 +1,17 @@
{
"name": "corePluginStaticAssets",
"version": "1.0.0",
"main": "target/test/plugin_functional/plugins/core_plugin_static_assets",
"kibana": {
"version": "kibana",
"templateVersion": "1.0.0"
},
"license": "Apache-2.0",
"scripts": {
"kbn": "node ../../../../scripts/kbn.js",
"build": "rm -rf './target' && tsc"
},
"devDependencies": {
"typescript": "3.7.2"
}
}

View file

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="24" viewBox="0 0 36 24">
<g fill="none" fill-rule="evenodd">
<path fill="#69707D" fill-rule="nonzero" d="M8,8 C8.55228,8 9,8.44772 9,9 L9,22 C9,22.5523 8.55228,23 8,23 L4,23 C3.44772,23 3,22.5523 3,22 L3,9 C3,8.44772 3.44772,8 4,8 L8,8 Z M24,1 C24.5523,1 25,1.44772 25,2 L25,22 C25,22.5523 24.5523,23 24,23 L20,23 C19.4477,23 19,22.5523 19,22 L19,2 C19,1.44772 19.4477,1 20,1 L24,1 Z"/>
<path fill="#54B399" fill-rule="nonzero" d="M16,12 C16.5523,12 17,12.4477 17,13 L17,22 C17,22.5523 16.5523,23 16,23 L12,23 C11.4477,23 11,22.5523 11,22 L11,13 C11,12.4477 11.4477,12 12,12 L16,12 Z M32,5 C32.5523,5 33,5.44772 33,6 L33,22 C33,22.5523 32.5523,23 32,23 L28,23 C27.4477,23 27,22.5523 27,22 L27,6 C27,5.44772 27.4477,5 28,5 L32,5 Z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 816 B

Some files were not shown because too many files have changed in this diff Show more