diff --git a/examples/embeddable_examples/tsconfig.json b/examples/embeddable_examples/tsconfig.json index 23cf4052c7919..38e4db3d9946f 100644 --- a/examples/embeddable_examples/tsconfig.json +++ b/examples/embeddable_examples/tsconfig.json @@ -24,7 +24,6 @@ "@kbn/data-plugin", "@kbn/charts-plugin", "@kbn/field-formats-plugin", - "@kbn/content-management-utils", "@kbn/core-lifecycle-browser", "@kbn/presentation-util-plugin", "@kbn/unified-field-list", @@ -39,6 +38,7 @@ "@kbn/kibana-utils-plugin", "@kbn/core-mount-utils-browser", "@kbn/react-kibana-mount", - "@kbn/shared-ux-router" + "@kbn/shared-ux-router", + "@kbn/config-schema" ] } diff --git a/src/platform/plugins/shared/dashboard/server/dashboard_saved_object/migrations/dashboard_saved_object_migrations.ts b/src/platform/plugins/shared/dashboard/server/dashboard_saved_object/migrations/dashboard_saved_object_migrations.ts index f90d704690a5a..67cc5cf7b21a2 100644 --- a/src/platform/plugins/shared/dashboard/server/dashboard_saved_object/migrations/dashboard_saved_object_migrations.ts +++ b/src/platform/plugins/shared/dashboard/server/dashboard_saved_object/migrations/dashboard_saved_object_migrations.ts @@ -23,15 +23,15 @@ import { migrateByValueDashboardPanels } from './migrate_by_value_dashboard_pane import { createExtractPanelReferencesMigration } from './migrate_extract_panel_references'; export interface DashboardSavedObjectTypeMigrationsDeps { - embeddable: EmbeddableSetup; - core: CoreSetup<{ embeddable: EmbeddableStart }>; + embeddableSetup: EmbeddableSetup; + getEmbeddableStart: () => EmbeddableStart | undefined; } export const createDashboardSavedObjectTypeMigrations = ( deps: DashboardSavedObjectTypeMigrationsDeps ): SavedObjectMigrationMap => { const embeddableMigrations = mapValues( - deps.embeddable.getAllMigrations(), + deps.embeddableSetup.getAllMigrations(), migrateByValueDashboardPanels ); @@ -40,7 +40,7 @@ export const createDashboardSavedObjectTypeMigrations = ( '7.0.0': flow(migrations700), '7.3.0': flow(migrations730), '7.9.3': flow(migrateMatchAllQuery), - '7.11.0': flow(createExtractPanelReferencesMigration(deps)), + '7.11.0': createExtractPanelReferencesMigration(deps), '7.14.0': flow(replaceIndexPatternReference), '7.17.3': flow(migrateExplicitlyHiddenTitles), }; diff --git a/src/platform/plugins/shared/dashboard/server/dashboard_saved_object/migrations/migrate_extract_panel_references.ts b/src/platform/plugins/shared/dashboard/server/dashboard_saved_object/migrations/migrate_extract_panel_references.ts index ecad01ecf6481..227de671e5afc 100644 --- a/src/platform/plugins/shared/dashboard/server/dashboard_saved_object/migrations/migrate_extract_panel_references.ts +++ b/src/platform/plugins/shared/dashboard/server/dashboard_saved_object/migrations/migrate_extract_panel_references.ts @@ -7,10 +7,10 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import { inspect } from 'util'; import { SavedObject, SavedObjectMigrationParams } from '@kbn/core-saved-objects-server'; -import { EmbeddableStart } from '@kbn/embeddable-plugin/server'; -import type { DashboardSavedObjectTypeMigrationsDeps } from './dashboard_saved_object_migrations'; import type { DashboardSavedObjectAttributes } from '../schema'; +import type { DashboardSavedObjectTypeMigrationsDeps } from './dashboard_saved_object_migrations'; import { itemToSavedObject, savedObjectToItem } from '../../content_management/latest'; /** @@ -22,26 +22,36 @@ import { itemToSavedObject, savedObjectToItem } from '../../content_management/l * 1. In addition to regular `panel_` we will get new references which are extracted by `embeddablePersistableStateService` (dashboard drilldown references) * 2. `panel_` references will be regenerated * All other references like index-patterns are forwarded non touched - * @param deps + * + * This migration uses the deferred flag on {@link SavedObjectMigrationParams | SavedObjectMigrationParams} which means the + * migration only runs when the saved object is accessed. This ensures that the embeddable service is available and can be + * used to extract the references correctly. */ export function createExtractPanelReferencesMigration( deps: DashboardSavedObjectTypeMigrationsDeps ): SavedObjectMigrationParams { - let embeddableStart: EmbeddableStart; - void deps.core.getStartServices().then(([_, { embeddable }]) => { - embeddableStart = embeddable; - }); return { deferred: true, - transform: (doc) => { + transform: (doc, { log }) => { const references = doc.references ?? []; - + const getExceptionMessage = (error: Error) => + `Exception @ createExtractPanelReferencesMigration while trying to extract dashboard panels!\n` + + `${error.stack}\n` + + `dashboard: ${inspect(doc, false, null)}`; /** * Remembering this because dashboard's extractReferences won't return those * All other references like `panel_` will be overwritten */ const oldNonPanelReferences = references.filter((ref) => !ref.name.startsWith('panel_')); + const embeddableStart = deps.getEmbeddableStart(); + if (!embeddableStart) { + log.warn( + `Exception @ createExtractPanelReferencesMigration!\nEmbeddable start service is not available.` + ); + return doc; + } + // Content Management transform functions `savedObjectToItem` and `itemToSavedObject` // will run embeddable inject and extract functions for each panel const { item, error: itemError } = savedObjectToItem( @@ -50,14 +60,20 @@ export function createExtractPanelReferencesMigration( false ); - if (itemError) throw itemError; + if (itemError) { + log.warn(getExceptionMessage(itemError)); + return doc; + } const { attributes, error: attributesError, references: newPanelReferences, } = itemToSavedObject({ attributes: item.attributes, embeddable: embeddableStart }); - if (attributesError) throw attributesError; + if (attributesError) { + log.warn(getExceptionMessage(attributesError)); + return doc; + } return { ...doc, diff --git a/src/platform/plugins/shared/dashboard/server/plugin.ts b/src/platform/plugins/shared/dashboard/server/plugin.ts index d165f0bb2d5cc..78e6cb75751f8 100644 --- a/src/platform/plugins/shared/dashboard/server/plugin.ts +++ b/src/platform/plugins/shared/dashboard/server/plugin.ts @@ -7,18 +7,11 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { - TaskManagerSetupContract, - TaskManagerStartContract, -} from '@kbn/task-manager-plugin/server'; -import { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/server'; -import { UsageCollectionSetup, UsageCollectionStart } from '@kbn/usage-collection-plugin/server'; import { ContentManagementServerSetup } from '@kbn/content-management-plugin/server'; -import { SharePluginStart } from '@kbn/share-plugin/server'; import { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from '@kbn/core/server'; import { registerContentInsights } from '@kbn/content-management-content-insights-server'; -import type { SavedObjectTaggingStart } from '@kbn/saved-objects-tagging-plugin/server'; +import { EmbeddableStart } from '@kbn/embeddable-plugin/server'; import { initializeDashboardTelemetryTask, scheduleDashboardTelemetry, @@ -27,7 +20,12 @@ import { import { getUISettings } from './ui_settings'; import { DashboardStorage } from './content_management'; import { capabilitiesProvider } from './capabilities_provider'; -import { DashboardPluginSetup, DashboardPluginStart } from './types'; +import { + DashboardPluginSetup, + DashboardPluginStart, + DashboardSetupDeps, + DashboardStartDeps, +} from './types'; import { createDashboardSavedObjectType } from './dashboard_saved_object'; import { CONTENT_ID, LATEST_VERSION } from '../common/content_management'; import { registerDashboardUsageCollector } from './usage/register_collector'; @@ -35,39 +33,29 @@ import { dashboardPersistableStateServiceFactory } from './dashboard_container/d import { registerAPIRoutes } from './api'; import { DashboardAppLocatorDefinition } from '../common/locator/locator'; -interface SetupDeps { - embeddable: EmbeddableSetup; - usageCollection?: UsageCollectionSetup; - taskManager: TaskManagerSetupContract; - contentManagement: ContentManagementServerSetup; -} - -interface StartDeps { - embeddable: EmbeddableStart; - taskManager: TaskManagerStartContract; - usageCollection?: UsageCollectionStart; - savedObjectsTagging?: SavedObjectTaggingStart; - share?: SharePluginStart; -} - export class DashboardPlugin - implements Plugin + implements + Plugin { private contentClient?: ReturnType['contentClient']; + private embeddableService?: EmbeddableStart; private readonly logger: Logger; constructor(private initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); } - public setup(core: CoreSetup, plugins: SetupDeps) { + public setup( + core: CoreSetup, + plugins: DashboardSetupDeps + ) { this.logger.debug('dashboard: Setup'); core.savedObjects.registerType( createDashboardSavedObjectType({ migrationDeps: { - core, - embeddable: plugins.embeddable, + embeddableSetup: plugins.embeddable, + getEmbeddableStart: () => this.embeddableService, }, }) ); @@ -136,8 +124,11 @@ export class DashboardPlugin return {}; } - public start(core: CoreStart, plugins: StartDeps) { + public start(core: CoreStart, plugins: DashboardStartDeps) { this.logger.debug('dashboard: Started'); + if (plugins.embeddable) { + this.embeddableService = plugins.embeddable; + } if (plugins.share) { plugins.share.url.locators.create( diff --git a/src/platform/plugins/shared/dashboard/server/types.ts b/src/platform/plugins/shared/dashboard/server/types.ts index 9c3edc6a4abad..f2db0a5b5e01e 100644 --- a/src/platform/plugins/shared/dashboard/server/types.ts +++ b/src/platform/plugins/shared/dashboard/server/types.ts @@ -8,6 +8,29 @@ */ import { ContentManagementServerSetup } from '@kbn/content-management-plugin/server'; +import { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/server'; +import { SavedObjectTaggingStart } from '@kbn/saved-objects-tagging-plugin/server'; +import { SharePluginStart } from '@kbn/share-plugin/server'; +import { + TaskManagerSetupContract, + TaskManagerStartContract, +} from '@kbn/task-manager-plugin/server'; +import { UsageCollectionSetup, UsageCollectionStart } from '@kbn/usage-collection-plugin/server'; + +export interface DashboardSetupDeps { + embeddable: EmbeddableSetup; + usageCollection?: UsageCollectionSetup; + taskManager: TaskManagerSetupContract; + contentManagement: ContentManagementServerSetup; +} + +export interface DashboardStartDeps { + embeddable: EmbeddableStart; + taskManager: TaskManagerStartContract; + usageCollection?: UsageCollectionStart; + savedObjectsTagging?: SavedObjectTaggingStart; + share?: SharePluginStart; +} // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface DashboardPluginSetup {} diff --git a/src/platform/plugins/shared/embeddable/tsconfig.json b/src/platform/plugins/shared/embeddable/tsconfig.json index e424383d3441a..012e2c076f345 100644 --- a/src/platform/plugins/shared/embeddable/tsconfig.json +++ b/src/platform/plugins/shared/embeddable/tsconfig.json @@ -24,6 +24,7 @@ "@kbn/react-kibana-mount", "@kbn/analytics", "@kbn/ui-theme", + "@kbn/config-schema", ], "exclude": ["target/**/*"] }