diff --git a/packages/core/apps/core-apps-server-internal/src/core_app.test.ts b/packages/core/apps/core-apps-server-internal/src/core_app.test.ts index f0bde326b7b74..153a283fe5696 100644 --- a/packages/core/apps/core-apps-server-internal/src/core_app.test.ts +++ b/packages/core/apps/core-apps-server-internal/src/core_app.test.ts @@ -217,6 +217,73 @@ describe('CoreApp', () => { bypassErrorFormat: true, }); }); + + it('registers expected static dirs if there are public plugins', () => { + prebootUIPlugins.internal.set('some-plugin', { + publicAssetsDir: '/foo', + publicTargetDir: '/bar', + requiredBundles: [], + version: '1.0.0', + }); + prebootUIPlugins.public.set('some-plugin-2', { + type: PluginType.preboot, + configPath: 'some-plugin-2', + id: 'some-plugin-2', + optionalPlugins: [], + requiredBundles: [], + requiredPlugins: [], + runtimePluginDependencies: [], + }); + prebootUIPlugins.internal.set('some-plugin-2', { + publicAssetsDir: '/foo', + publicTargetDir: '/bar', + requiredBundles: [], + version: '1.0.0', + }); + + internalCorePreboot.http.staticAssets.prependServerPath.mockReturnValue( + '/static-assets-path' + ); + internalCorePreboot.http.staticAssets.getPluginServerPath.mockImplementation( + (name: string, path: string) => `/static-assets-path/${name}/${path}` + ); + coreApp.preboot(internalCorePreboot, prebootUIPlugins); + + expect(internalCorePreboot.http.registerStaticDir).toHaveBeenCalledTimes( + // Twice for all UI plugins + core's UI asset routes + prebootUIPlugins.public.size * 2 + 2 + ); + expect(internalCorePreboot.http.registerStaticDir).toHaveBeenCalledWith( + '/static-assets-path', + expect.any(String) + ); + expect(internalCorePreboot.http.registerStaticDir).toHaveBeenCalledWith( + '/ui/{path*}', + expect.any(String) + ); + expect(internalCorePreboot.http.registerStaticDir).toHaveBeenCalledWith( + '/static-assets-path/some-plugin/{path*}', + expect.any(String) + ); + expect(internalCorePreboot.http.registerStaticDir).toHaveBeenCalledWith( + '/plugins/some-plugin/assets/{path*}', // legacy + expect.any(String) + ); + expect(internalCorePreboot.http.registerStaticDir).toHaveBeenCalledWith( + '/static-assets-path/some-plugin-2/{path*}', + expect.any(String) + ); + expect(internalCorePreboot.http.registerStaticDir).toHaveBeenCalledWith( + '/plugins/some-plugin-2/assets/{path*}', // legacy + expect.any(String) + ); + }); + + it('does not register any static dirs if there are no public plugins', () => { + prebootUIPlugins = emptyPlugins(); + coreApp.preboot(internalCorePreboot, prebootUIPlugins); + expect(internalCorePreboot.http.registerStaticDir).toHaveBeenCalledTimes(0); + }); }); describe('`/app/{id}/{any*}` route', () => { @@ -249,19 +316,72 @@ describe('CoreApp', () => { }); }); - it('registers SHA-scoped and non-SHA-scoped UI bundle routes', async () => { + it('registers expected static dirs if there are public plugins', async () => { const uiPlugins = emptyPlugins(); - internalCoreSetup.http.staticAssets.prependServerPath.mockReturnValue('/some-path'); + uiPlugins.public.set('some-plugin', { + type: PluginType.preboot, + configPath: 'some-plugin', + id: 'some-plugin', + optionalPlugins: [], + requiredBundles: [], + requiredPlugins: [], + runtimePluginDependencies: [], + }); + uiPlugins.internal.set('some-plugin', { + publicAssetsDir: '/foo', + publicTargetDir: '/bar', + requiredBundles: [], + version: '1.0.0', + }); + uiPlugins.public.set('some-plugin-2', { + type: PluginType.preboot, + configPath: 'some-plugin-2', + id: 'some-plugin-2', + optionalPlugins: [], + requiredBundles: [], + requiredPlugins: [], + runtimePluginDependencies: [], + }); + uiPlugins.internal.set('some-plugin-2', { + publicAssetsDir: '/foo', + publicTargetDir: '/bar', + requiredBundles: [], + version: '1.0.0', + }); + + internalCoreSetup.http.staticAssets.prependServerPath.mockReturnValue('/static-assets-path'); + internalCoreSetup.http.staticAssets.getPluginServerPath.mockImplementation( + (name: string, path: string) => `/static-assets-path/${name}/${path}` + ); await coreApp.setup(internalCoreSetup, uiPlugins); - expect(internalCoreSetup.http.registerStaticDir).toHaveBeenCalledTimes(2); + expect(internalCoreSetup.http.registerStaticDir).toHaveBeenCalledTimes( + // Twice for all UI plugins + core's UI asset routes + uiPlugins.public.size * 2 + 2 + ); expect(internalCoreSetup.http.registerStaticDir).toHaveBeenCalledWith( - '/some-path', + '/static-assets-path', expect.any(String) ); expect(internalCoreSetup.http.registerStaticDir).toHaveBeenCalledWith( '/ui/{path*}', expect.any(String) ); + expect(internalCoreSetup.http.registerStaticDir).toHaveBeenCalledWith( + '/static-assets-path/some-plugin/{path*}', + expect.any(String) + ); + expect(internalCoreSetup.http.registerStaticDir).toHaveBeenCalledWith( + '/plugins/some-plugin/assets/{path*}', // legacy + expect.any(String) + ); + expect(internalCoreSetup.http.registerStaticDir).toHaveBeenCalledWith( + '/static-assets-path/some-plugin-2/{path*}', + expect.any(String) + ); + expect(internalCoreSetup.http.registerStaticDir).toHaveBeenCalledWith( + '/plugins/some-plugin-2/assets/{path*}', // legacy + expect.any(String) + ); }); }); diff --git a/packages/core/apps/core-apps-server-internal/src/core_app.ts b/packages/core/apps/core-apps-server-internal/src/core_app.ts index 1e54d7d8aaa26..a65b3373b2e83 100644 --- a/packages/core/apps/core-apps-server-internal/src/core_app.ts +++ b/packages/core/apps/core-apps-server-internal/src/core_app.ts @@ -63,7 +63,7 @@ export class CoreAppsService { // We register app-serving routes only if there are `preboot` plugins that may need them. if (uiPlugins.public.size > 0) { this.registerPrebootDefaultRoutes(corePreboot, uiPlugins); - this.registerStaticDirs(corePreboot); + this.registerStaticDirs(corePreboot, uiPlugins); } } @@ -71,7 +71,7 @@ export class CoreAppsService { this.logger.debug('Setting up core app.'); const config = await firstValueFrom(this.config$); this.registerDefaultRoutes(coreSetup, uiPlugins, config); - this.registerStaticDirs(coreSetup); + this.registerStaticDirs(coreSetup, uiPlugins); } private registerPrebootDefaultRoutes(corePreboot: InternalCorePreboot, uiPlugins: UiPlugins) { @@ -271,7 +271,7 @@ export class CoreAppsService { // After the package is built and bootstrap extracts files to bazel-bin, // assets are exposed at the root of the package and in the package's node_modules dir - private registerStaticDirs(core: InternalCoreSetup | InternalCorePreboot) { + private registerStaticDirs(core: InternalCoreSetup | InternalCorePreboot, uiPlugins: UiPlugins) { /** * Serve UI from sha-scoped and not-sha-scoped paths to allow time for plugin code to migrate * Eventually we only want to serve from the sha scoped path @@ -282,5 +282,20 @@ export class CoreAppsService { fromRoot('node_modules/@kbn/core-apps-server-internal/assets') ); }); + + for (const [pluginName] of uiPlugins.public) { + const pluginInfo = uiPlugins.internal.get(pluginName); + if (!pluginInfo) continue; // assuming we will never hit this case; a public entry should have internal info registered + /** + * Serve UI from sha-scoped and not-sha-scoped paths to allow time for plugin code to migrate + * Eventually we only want to serve from the sha scoped path + */ + [ + core.http.staticAssets.getPluginServerPath(pluginName, '{path*}'), + `/plugins/${pluginName}/assets/{path*}`, + ].forEach((path) => { + core.http.registerStaticDir(path, pluginInfo.publicAssetsDir); + }); + } } } diff --git a/packages/core/plugins/core-plugins-server-internal/src/plugins_service.test.ts b/packages/core/plugins/core-plugins-server-internal/src/plugins_service.test.ts index e25a1b924e420..7d0df69b23891 100644 --- a/packages/core/plugins/core-plugins-server-internal/src/plugins_service.test.ts +++ b/packages/core/plugins/core-plugins-server-internal/src/plugins_service.test.ts @@ -1301,31 +1301,6 @@ describe('PluginsService', () => { expect(standardMockPluginSystem.setupPlugins).not.toHaveBeenCalled(); }); - it('#preboot registers expected static dirs', async () => { - prebootDeps.http.staticAssets.getPluginServerPath.mockImplementation( - (pluginName: string) => `/static-assets/${pluginName}` - ); - await pluginsService.discover({ environment: environmentPreboot, node: nodePreboot }); - await pluginsService.preboot(prebootDeps); - expect(prebootDeps.http.registerStaticDir).toHaveBeenCalledTimes(prebootPlugins.length * 2); - expect(prebootDeps.http.registerStaticDir).toHaveBeenCalledWith( - '/static-assets/plugin-1-preboot', - expect.any(String) - ); - expect(prebootDeps.http.registerStaticDir).toHaveBeenCalledWith( - '/plugins/plugin-1-preboot/assets/{path*}', - expect.any(String) - ); - expect(prebootDeps.http.registerStaticDir).toHaveBeenCalledWith( - '/static-assets/plugin-2-preboot', - expect.any(String) - ); - expect(prebootDeps.http.registerStaticDir).toHaveBeenCalledWith( - '/plugins/plugin-2-preboot/assets/{path*}', - expect.any(String) - ); - }); - it('#setup does initialize `standard` plugins if plugins.initialize is true', async () => { config$.next({ plugins: { initialize: true } }); await pluginsService.discover({ environment: environmentPreboot, node: nodePreboot }); @@ -1346,32 +1321,6 @@ describe('PluginsService', () => { expect(prebootMockPluginSystem.setupPlugins).not.toHaveBeenCalled(); expect(initialized).toBe(false); }); - - it('#setup registers expected static dirs', async () => { - await pluginsService.discover({ environment: environmentPreboot, node: nodePreboot }); - await pluginsService.preboot(prebootDeps); - setupDeps.http.staticAssets.getPluginServerPath.mockImplementation( - (pluginName: string) => `/static-assets/${pluginName}` - ); - await pluginsService.setup(setupDeps); - expect(setupDeps.http.registerStaticDir).toHaveBeenCalledTimes(standardPlugins.length * 2); - expect(setupDeps.http.registerStaticDir).toHaveBeenCalledWith( - '/static-assets/plugin-1-standard', - expect.any(String) - ); - expect(setupDeps.http.registerStaticDir).toHaveBeenCalledWith( - '/plugins/plugin-1-standard/assets/{path*}', - expect.any(String) - ); - expect(setupDeps.http.registerStaticDir).toHaveBeenCalledWith( - '/static-assets/plugin-2-standard', - expect.any(String) - ); - expect(setupDeps.http.registerStaticDir).toHaveBeenCalledWith( - '/plugins/plugin-2-standard/assets/{path*}', - expect.any(String) - ); - }); }); describe('#getExposedPluginConfigsToUsage', () => { diff --git a/packages/core/plugins/core-plugins-server-internal/src/plugins_service.ts b/packages/core/plugins/core-plugins-server-internal/src/plugins_service.ts index da5d77d8be675..bb5ce353c3492 100644 --- a/packages/core/plugins/core-plugins-server-internal/src/plugins_service.ts +++ b/packages/core/plugins/core-plugins-server-internal/src/plugins_service.ts @@ -150,7 +150,6 @@ export class PluginsService const config = await firstValueFrom(this.config$); if (config.initialize) { await this.prebootPluginsSystem.setupPlugins(deps); - this.registerPluginStaticDirs(deps, this.prebootUiPluginInternalInfo); } else { this.log.info( 'Skipping `setup` for `preboot` plugins since plugin initialization is disabled.' @@ -166,7 +165,6 @@ export class PluginsService let contracts = new Map(); if (config.initialize) { contracts = await this.standardPluginsSystem.setupPlugins(deps); - this.registerPluginStaticDirs(deps, this.standardUiPluginInternalInfo); } else { this.log.info( 'Skipping `setup` for `standard` plugins since plugin initialization is disabled.' @@ -442,22 +440,4 @@ export class PluginsService missingOrIncompatibleDependencies, }; } - - private registerPluginStaticDirs( - deps: PluginsServiceSetupDeps | PluginsServicePrebootSetupDeps, - uiPluginInternalInfo: Map - ) { - for (const [pluginName, pluginInfo] of uiPluginInternalInfo) { - /** - * Serve UI from sha-scoped and not-sha-scoped paths to allow time for plugin code to migrate - * Eventually we only want to serve from the sha scoped path - */ - [ - deps.http.staticAssets.getPluginServerPath(pluginName, '{path*}'), - `/plugins/${pluginName}/assets/{path*}`, - ].forEach((path) => { - deps.http.registerStaticDir(path, pluginInfo.publicAssetsDir); - }); - } - } }