```
## Properties
diff --git a/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.md b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.md
index de46d91d90c65..681c671403315 100644
--- a/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.md
+++ b/docs/development/plugins/embeddable/server/kibana-plugin-plugins-embeddable-server.embeddableregistrydefinition.md
@@ -7,7 +7,7 @@
Signature:
```typescript
-export interface EmbeddableRegistryDefinition extends PersistableStateDefinition
+export interface EmbeddableRegistryDefinition
extends PersistableStateDefinition
```
## Properties
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.md
index 3cc38a0cbdc0f..6835188c2fb04 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.md
@@ -7,7 +7,7 @@
Signature:
```typescript
-export declare class Executor = Record> implements PersistableState
+export declare class Executor = Record> implements PersistableStateService
```
## Constructors
@@ -40,7 +40,6 @@ export declare class Executor = Record
-
-[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [Executor](./kibana-plugin-plugins-expressions-public.executor.md) > [migrateToLatest](./kibana-plugin-plugins-expressions-public.executor.migratetolatest.md)
-
-## Executor.migrateToLatest() method
-
-Signature:
-
-```typescript
-migrateToLatest(ast: unknown, version: string): ExpressionAstExpression;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| ast | unknown
| |
-| version | string
| |
-
-Returns:
-
-`ExpressionAstExpression`
-
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.md
index 307fc73ec6e9c..6ba0f0feb82b3 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.md
@@ -15,7 +15,7 @@ so that JSDoc appears in developers IDE when they use those `plugins.expressions
Signature:
```typescript
-export declare class ExpressionsService implements PersistableState
+export declare class ExpressionsService implements PersistableStateService
```
## Constructors
@@ -39,8 +39,7 @@ export declare class ExpressionsService implements PersistableStateExpressionsServiceStart['getType'] | |
| [getTypes](./kibana-plugin-plugins-expressions-public.expressionsservice.gettypes.md) | | () => ReturnType<Executor['getTypes']>
| Returns POJO map of all registered expression types, where keys are names of the types and values are ExpressionType
instances. |
| [inject](./kibana-plugin-plugins-expressions-public.expressionsservice.inject.md) | | (state: ExpressionAstExpression, references: SavedObjectReference[]) => ExpressionAstExpression
| Injects saved object references into expression AST |
-| [migrate](./kibana-plugin-plugins-expressions-public.expressionsservice.migrate.md) | | (state: SerializableState, version: string) => ExpressionAstExpression
| Injects saved object references into expression AST |
-| [migrateToLatest](./kibana-plugin-plugins-expressions-public.expressionsservice.migratetolatest.md) | | (state: unknown, version: string) => ExpressionAstExpression
| Injects saved object references into expression AST |
+| [migrate](./kibana-plugin-plugins-expressions-public.expressionsservice.migrate.md) | | (state: SerializableState, version: string) => ExpressionAstExpression
| Runs the migration (if it exists) for specified version. This will run a single migration step (ie from 7.10.0 to 7.10.1) |
| [registerFunction](./kibana-plugin-plugins-expressions-public.expressionsservice.registerfunction.md) | | (functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)) => void
| Register an expression function, which will be possible to execute as part of the expression pipeline.Below we register a function which simply sleeps for given number of milliseconds to delay the execution and outputs its input as-is.
```ts
expressions.registerFunction({
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.migrate.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.migrate.md
index 88a6bda4ee3f5..d1f24bfcfc0bb 100644
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.migrate.md
+++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.migrate.md
@@ -4,7 +4,7 @@
## ExpressionsService.migrate property
-Injects saved object references into expression AST
+Runs the migration (if it exists) for specified version. This will run a single migration step (ie from 7.10.0 to 7.10.1)
Signature:
diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.migratetolatest.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.migratetolatest.md
deleted file mode 100644
index e6860df19fd3f..0000000000000
--- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.migratetolatest.md
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ExpressionsService](./kibana-plugin-plugins-expressions-public.expressionsservice.md) > [migrateToLatest](./kibana-plugin-plugins-expressions-public.expressionsservice.migratetolatest.md)
-
-## ExpressionsService.migrateToLatest property
-
-Injects saved object references into expression AST
-
-Signature:
-
-```typescript
-readonly migrateToLatest: (state: unknown, version: string) => ExpressionAstExpression;
-```
diff --git a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.md b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.md
index da20ae4aa892e..48002a9f986df 100644
--- a/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.md
+++ b/docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.md
@@ -7,7 +7,7 @@
Signature:
```typescript
-export declare class Executor = Record> implements PersistableState
+export declare class Executor = Record> implements PersistableStateService
```
## Constructors
@@ -40,7 +40,6 @@ export declare class Executor = Record
-
-[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [Executor](./kibana-plugin-plugins-expressions-server.executor.md) > [migrateToLatest](./kibana-plugin-plugins-expressions-server.executor.migratetolatest.md)
-
-## Executor.migrateToLatest() method
-
-Signature:
-
-```typescript
-migrateToLatest(ast: unknown, version: string): ExpressionAstExpression;
-```
-
-## Parameters
-
-| Parameter | Type | Description |
-| --- | --- | --- |
-| ast | unknown
| |
-| version | string
| |
-
-Returns:
-
-`ExpressionAstExpression`
-
diff --git a/src/plugins/embeddable/common/lib/extract.ts b/src/plugins/embeddable/common/lib/extract.ts
new file mode 100644
index 0000000000000..966d3f81a36c3
--- /dev/null
+++ b/src/plugins/embeddable/common/lib/extract.ts
@@ -0,0 +1,54 @@
+/*
+ * 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 { CommonEmbeddableStartContract, EmbeddableStateWithType } from '../types';
+import { extractBaseEmbeddableInput } from './migrate_base_input';
+import { SerializableState } from '../../../kibana_utils/common/persistable_state';
+
+export const getExtractFunction = (embeddables: CommonEmbeddableStartContract) => {
+ return (state: EmbeddableStateWithType) => {
+ const enhancements = state.enhancements || {};
+ const factory = embeddables.getEmbeddableFactory(state.type);
+
+ const baseResponse = extractBaseEmbeddableInput(state);
+ let updatedInput = baseResponse.state;
+ const refs = baseResponse.references;
+
+ if (factory) {
+ const factoryResponse = factory.extract(state);
+ updatedInput = factoryResponse.state;
+ refs.push(...factoryResponse.references);
+ }
+
+ updatedInput.enhancements = {};
+ Object.keys(enhancements).forEach((key) => {
+ if (!enhancements[key]) return;
+ const enhancementResult = embeddables
+ .getEnhancement(key)
+ .extract(enhancements[key] as SerializableState);
+ refs.push(...enhancementResult.references);
+ updatedInput.enhancements![key] = enhancementResult.state;
+ });
+
+ return {
+ state: updatedInput,
+ references: refs,
+ };
+ };
+};
diff --git a/src/plugins/embeddable/common/lib/index.ts b/src/plugins/embeddable/common/lib/index.ts
new file mode 100644
index 0000000000000..e180ca9489df0
--- /dev/null
+++ b/src/plugins/embeddable/common/lib/index.ts
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+export * from './extract';
+export * from './inject';
+export * from './migrate';
+export * from './migrate_base_input';
+export * from './telemetry';
diff --git a/src/plugins/embeddable/common/lib/inject.ts b/src/plugins/embeddable/common/lib/inject.ts
new file mode 100644
index 0000000000000..8cba3e9da7355
--- /dev/null
+++ b/src/plugins/embeddable/common/lib/inject.ts
@@ -0,0 +1,46 @@
+/*
+ * 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 { CommonEmbeddableStartContract, EmbeddableStateWithType } from '../types';
+import { SavedObjectReference } from '../../../../core/types';
+import { injectBaseEmbeddableInput } from './migrate_base_input';
+import { SerializableState } from '../../../kibana_utils/common/persistable_state';
+
+export const getInjectFunction = (embeddables: CommonEmbeddableStartContract) => {
+ return (state: EmbeddableStateWithType, references: SavedObjectReference[]) => {
+ const enhancements = state.enhancements || {};
+ const factory = embeddables.getEmbeddableFactory(state.type);
+
+ let updatedInput = injectBaseEmbeddableInput(state, references);
+
+ if (factory) {
+ updatedInput = factory.inject(updatedInput, references);
+ }
+
+ updatedInput.enhancements = {};
+ Object.keys(enhancements).forEach((key) => {
+ if (!enhancements[key]) return;
+ updatedInput.enhancements![key] = embeddables
+ .getEnhancement(key)
+ .inject(enhancements[key] as SerializableState, references);
+ });
+
+ return updatedInput;
+ };
+};
diff --git a/src/plugins/embeddable/common/lib/migrate.ts b/src/plugins/embeddable/common/lib/migrate.ts
new file mode 100644
index 0000000000000..e22e591212251
--- /dev/null
+++ b/src/plugins/embeddable/common/lib/migrate.ts
@@ -0,0 +1,47 @@
+/*
+ * 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 { CommonEmbeddableStartContract } from '../types';
+import { baseEmbeddableMigrations } from './migrate_base_input';
+import { SerializableState } from '../../../kibana_utils/common/persistable_state';
+
+export const getMigrateFunction = (embeddables: CommonEmbeddableStartContract) => {
+ return (state: SerializableState, version: string) => {
+ const enhancements = (state.enhancements as SerializableState) || {};
+ const factory = embeddables.getEmbeddableFactory(state.type as string);
+
+ let updatedInput = baseEmbeddableMigrations[version]
+ ? baseEmbeddableMigrations[version](state)
+ : state;
+
+ if (factory && factory.migrations[version]) {
+ updatedInput = factory.migrations[version](updatedInput);
+ }
+
+ updatedInput.enhancements = {};
+ Object.keys(enhancements).forEach((key) => {
+ if (!enhancements[key]) return;
+ (updatedInput.enhancements! as Record)[key] = embeddables
+ .getEnhancement(key)
+ .migrations[version](enhancements[key] as SerializableState);
+ });
+
+ return updatedInput;
+ };
+};
diff --git a/src/plugins/embeddable/common/lib/migrate_base_input.ts b/src/plugins/embeddable/common/lib/migrate_base_input.ts
index 0d5dc508e20ad..82dc30210c355 100644
--- a/src/plugins/embeddable/common/lib/migrate_base_input.ts
+++ b/src/plugins/embeddable/common/lib/migrate_base_input.ts
@@ -18,22 +18,25 @@
*/
import { SavedObjectReference } from '../../../../core/types';
-import { EmbeddableInput } from '../types';
+import { EmbeddableStateWithType } from '../types';
+import { MigrateFunctionsObject } from '../../../kibana_utils/common';
export const telemetryBaseEmbeddableInput = (
- state: EmbeddableInput,
+ state: EmbeddableStateWithType,
telemetryData: Record
) => {
return telemetryData;
};
-export const extractBaseEmbeddableInput = (state: EmbeddableInput) => {
+export const extractBaseEmbeddableInput = (state: EmbeddableStateWithType) => {
return { state, references: [] as SavedObjectReference[] };
};
export const injectBaseEmbeddableInput = (
- state: EmbeddableInput,
+ state: EmbeddableStateWithType,
references: SavedObjectReference[]
) => {
return state;
};
+
+export const baseEmbeddableMigrations: MigrateFunctionsObject = {};
diff --git a/src/plugins/embeddable/common/lib/telemetry.ts b/src/plugins/embeddable/common/lib/telemetry.ts
new file mode 100644
index 0000000000000..e2f5918b8080b
--- /dev/null
+++ b/src/plugins/embeddable/common/lib/telemetry.ts
@@ -0,0 +1,41 @@
+/*
+ * 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 { CommonEmbeddableStartContract, EmbeddableStateWithType } from '../types';
+import { telemetryBaseEmbeddableInput } from './migrate_base_input';
+
+export const getTelemetryFunction = (embeddables: CommonEmbeddableStartContract) => {
+ return (state: EmbeddableStateWithType, telemetryData: Record = {}) => {
+ const enhancements: Record = state.enhancements || {};
+ const factory = embeddables.getEmbeddableFactory(state.type);
+
+ let outputTelemetryData = telemetryBaseEmbeddableInput(state, telemetryData);
+ if (factory) {
+ outputTelemetryData = factory.telemetry(state, outputTelemetryData);
+ }
+ Object.keys(enhancements).map((key) => {
+ if (!enhancements[key]) return;
+ outputTelemetryData = embeddables
+ .getEnhancement(key)
+ .telemetry(enhancements[key], outputTelemetryData);
+ });
+
+ return outputTelemetryData;
+ };
+};
diff --git a/src/plugins/embeddable/common/types.ts b/src/plugins/embeddable/common/types.ts
index 2737f2678ff32..7e024eda9b793 100644
--- a/src/plugins/embeddable/common/types.ts
+++ b/src/plugins/embeddable/common/types.ts
@@ -73,3 +73,10 @@ export type EmbeddableInput = {
*/
searchSessionId?: string;
};
+
+export type EmbeddableStateWithType = EmbeddableInput & { type: string };
+
+export interface CommonEmbeddableStartContract {
+ getEmbeddableFactory: (embeddableFactoryId: string) => any;
+ getEnhancement: (enhancementId: string) => any;
+}
diff --git a/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts b/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts
index e2047dca1f770..6d5e7ef26b8cb 100644
--- a/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts
+++ b/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts
@@ -21,6 +21,7 @@ import { SavedObjectAttributes } from 'kibana/public';
import { EmbeddableFactoryDefinition } from './embeddable_factory_definition';
import { EmbeddableInput, EmbeddableOutput, IEmbeddable } from './i_embeddable';
import { EmbeddableFactory } from './embeddable_factory';
+import { EmbeddableStateWithType } from '../../../common/types';
import { IContainer } from '..';
export const defaultEmbeddableFactoryProvider = <
@@ -49,8 +50,9 @@ export const defaultEmbeddableFactoryProvider = <
getDisplayName: def.getDisplayName.bind(def),
savedObjectMetaData: def.savedObjectMetaData,
telemetry: def.telemetry || (() => ({})),
- inject: def.inject || ((state: EmbeddableInput) => state),
- extract: def.extract || ((state: EmbeddableInput) => ({ state, references: [] })),
+ inject: def.inject || ((state: EmbeddableStateWithType) => state),
+ extract: def.extract || ((state: EmbeddableStateWithType) => ({ state, references: [] })),
+ migrations: def.migrations || {},
};
return factory;
};
diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts b/src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts
index a6fa46fbc4e3e..5e718cd25f584 100644
--- a/src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts
+++ b/src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts
@@ -24,6 +24,7 @@ import { ErrorEmbeddable } from './error_embeddable';
import { IContainer } from '../containers/i_container';
import { PropertySpec } from '../types';
import { PersistableState } from '../../../../kibana_utils/common';
+import { EmbeddableStateWithType } from '../../../common/types';
export interface EmbeddableInstanceConfiguration {
id: string;
@@ -45,7 +46,7 @@ export interface EmbeddableFactory<
TEmbeddableOutput
>,
TSavedObjectAttributes extends SavedObjectAttributes = SavedObjectAttributes
-> extends PersistableState {
+> extends PersistableState {
// A unique identified for this factory, which will be used to map an embeddable spec to
// a factory that can generate an instance of it.
readonly type: string;
diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_factory_definition.ts b/src/plugins/embeddable/public/lib/embeddables/embeddable_factory_definition.ts
index 224a11a201b88..03b03f1ac6e91 100644
--- a/src/plugins/embeddable/public/lib/embeddables/embeddable_factory_definition.ts
+++ b/src/plugins/embeddable/public/lib/embeddables/embeddable_factory_definition.ts
@@ -43,5 +43,6 @@ export type EmbeddableFactoryDefinition<
| 'telemetry'
| 'extract'
| 'inject'
+ | 'migrations'
>
>;
diff --git a/src/plugins/embeddable/public/mocks.tsx b/src/plugins/embeddable/public/mocks.tsx
index 62063cb480338..c5a9860498117 100644
--- a/src/plugins/embeddable/public/mocks.tsx
+++ b/src/plugins/embeddable/public/mocks.tsx
@@ -123,6 +123,7 @@ const createStartContract = (): Start => {
telemetry: jest.fn(),
extract: jest.fn(),
inject: jest.fn(),
+ migrate: jest.fn(),
EmbeddablePanel: jest.fn(),
getEmbeddablePanel: jest.fn(),
getStateTransfer: jest.fn(() => createEmbeddableStateTransferMock() as EmbeddableStateTransfer),
diff --git a/src/plugins/embeddable/public/plugin.test.ts b/src/plugins/embeddable/public/plugin.test.ts
index 5fd3bcdd61318..5d47463344434 100644
--- a/src/plugins/embeddable/public/plugin.test.ts
+++ b/src/plugins/embeddable/public/plugin.test.ts
@@ -108,9 +108,11 @@ describe('embeddable factory', () => {
extract: jest.fn().mockImplementation((state) => ({ state, references: [] })),
inject: jest.fn().mockImplementation((state) => state),
telemetry: jest.fn().mockResolvedValue({}),
+ migrations: { '7.11.0': jest.fn().mockImplementation((state) => state) },
} as any;
const embeddableState = {
id: embeddableFactoryId,
+ type: embeddableFactoryId,
my: 'state',
} as any;
@@ -137,6 +139,11 @@ describe('embeddable factory', () => {
start.telemetry(embeddableState, {});
expect(embeddableFactory.telemetry).toBeCalledWith(embeddableState, {});
});
+
+ test('embeddableFactory migrate function gets called when calling embeddable migrate', () => {
+ start.migrate(embeddableState, '7.11.0');
+ expect(embeddableFactory.migrations['7.11.0']).toBeCalledWith(embeddableState);
+ });
});
describe('embeddable enhancements', () => {
@@ -149,6 +156,7 @@ describe('embeddable enhancements', () => {
extract: jest.fn().mockImplementation((state) => ({ state, references: [] })),
inject: jest.fn().mockImplementation((state) => state),
telemetry: jest.fn().mockResolvedValue({}),
+ migrations: { '7.11.0': jest.fn().mockImplementation((state) => state) },
} as any;
const embeddableState = {
enhancements: {
@@ -179,4 +187,11 @@ describe('embeddable enhancements', () => {
start.telemetry(embeddableState, {});
expect(embeddableEnhancement.telemetry).toBeCalledWith(embeddableState.enhancements.test, {});
});
+
+ test('enhancement migrate function gets called when calling embeddable migrate', () => {
+ start.migrate(embeddableState, '7.11.0');
+ expect(embeddableEnhancement.migrations['7.11.0']).toBeCalledWith(
+ embeddableState.enhancements.test
+ );
+ });
});
diff --git a/src/plugins/embeddable/public/plugin.tsx b/src/plugins/embeddable/public/plugin.tsx
index aa4d66c43c9db..4f3de0425579c 100644
--- a/src/plugins/embeddable/public/plugin.tsx
+++ b/src/plugins/embeddable/public/plugin.tsx
@@ -30,7 +30,6 @@ import {
Plugin,
ScopedHistory,
PublicAppInfo,
- SavedObjectReference,
} from '../../../core/public';
import {
EmbeddableFactoryRegistry,
@@ -51,14 +50,16 @@ import {
} from './lib';
import { EmbeddableFactoryDefinition } from './lib/embeddables/embeddable_factory_definition';
import { EmbeddableStateTransfer } from './lib/state_transfer';
-import {
- extractBaseEmbeddableInput,
- injectBaseEmbeddableInput,
- telemetryBaseEmbeddableInput,
-} from '../common/lib/migrate_base_input';
-import { PersistableState, SerializableState } from '../../kibana_utils/common';
+import { PersistableStateService, SerializableState } from '../../kibana_utils/common';
import { ATTRIBUTE_SERVICE_KEY, AttributeService } from './lib/attribute_service';
import { AttributeServiceOptions } from './lib/attribute_service/attribute_service';
+import { EmbeddableStateWithType } from '../common/types';
+import {
+ getExtractFunction,
+ getInjectFunction,
+ getMigrateFunction,
+ getTelemetryFunction,
+} from '../common/lib';
export interface EmbeddableSetupDependencies {
data: DataPublicPluginSetup;
@@ -84,7 +85,7 @@ export interface EmbeddableSetup {
setCustomEmbeddableFactoryProvider: (customProvider: EmbeddableFactoryProvider) => void;
}
-export interface EmbeddableStart extends PersistableState {
+export interface EmbeddableStart extends PersistableStateService {
getEmbeddableFactory: <
I extends EmbeddableInput = EmbeddableInput,
O extends EmbeddableOutput = EmbeddableOutput,
@@ -188,6 +189,11 @@ export class EmbeddablePublicPlugin implements Plugin
);
+ const commonContract = {
+ getEmbeddableFactory: this.getEmbeddableFactory,
+ getEnhancement: this.getEnhancement,
+ };
+
return {
getEmbeddableFactory: this.getEmbeddableFactory,
getEmbeddableFactories: this.getEmbeddableFactories,
@@ -207,9 +213,10 @@ export class EmbeddablePublicPlugin implements Plugin = {}) => {
- const enhancements: Record = state.enhancements || {};
- const factory = this.getEmbeddableFactory(state.id);
-
- let telemetry = telemetryBaseEmbeddableInput(state, telemetryData);
- if (factory) {
- telemetry = factory.telemetry(state, telemetry);
- }
- Object.keys(enhancements).map((key) => {
- if (!enhancements[key]) return;
- telemetry = this.getEnhancement(key).telemetry(enhancements[key], telemetry);
- });
-
- return telemetry;
- };
-
- private extract = (state: EmbeddableInput) => {
- const enhancements = state.enhancements || {};
- const factory = this.getEmbeddableFactory(state.id);
-
- const baseResponse = extractBaseEmbeddableInput(state);
- let updatedInput = baseResponse.state;
- const refs = baseResponse.references;
-
- if (factory) {
- const factoryResponse = factory.extract(state);
- updatedInput = factoryResponse.state;
- refs.push(...factoryResponse.references);
- }
-
- updatedInput.enhancements = {};
- Object.keys(enhancements).forEach((key) => {
- if (!enhancements[key]) return;
- const enhancementResult = this.getEnhancement(key).extract(
- enhancements[key] as SerializableState
- );
- refs.push(...enhancementResult.references);
- updatedInput.enhancements![key] = enhancementResult.state;
- });
-
- return {
- state: updatedInput,
- references: refs,
- };
- };
-
- private inject = (state: EmbeddableInput, references: SavedObjectReference[]) => {
- const enhancements = state.enhancements || {};
- const factory = this.getEmbeddableFactory(state.id);
-
- let updatedInput = injectBaseEmbeddableInput(state, references);
-
- if (factory) {
- updatedInput = factory.inject(updatedInput, references);
- }
-
- updatedInput.enhancements = {};
- Object.keys(enhancements).forEach((key) => {
- if (!enhancements[key]) return;
- updatedInput.enhancements![key] = this.getEnhancement(key).inject(
- enhancements[key] as SerializableState,
- references
- );
- });
-
- return updatedInput;
- };
-
private registerEnhancement = (enhancement: EnhancementRegistryDefinition) => {
if (this.enhancements.has(enhancement.id)) {
throw new Error(`enhancement with id ${enhancement.id} already exists in the registry`);
@@ -300,6 +239,7 @@ export class EmbeddablePublicPlugin implements Plugin {
return { state, references: [] };
}),
+ migrations: enhancement.migrations || {},
});
};
@@ -312,6 +252,7 @@ export class EmbeddablePublicPlugin implements Plugin {
return { state, references: [] };
},
+ migrations: {},
}
);
};
diff --git a/src/plugins/embeddable/public/public.api.md b/src/plugins/embeddable/public/public.api.md
index 983daa4d5af73..8f0f56c4e1a16 100644
--- a/src/plugins/embeddable/public/public.api.md
+++ b/src/plugins/embeddable/public/public.api.md
@@ -377,10 +377,11 @@ export interface EmbeddableEditorState {
}
// Warning: (ae-forgotten-export) The symbol "PersistableState" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "EmbeddableStateWithType" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "EmbeddableFactory" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
-export interface EmbeddableFactory = IEmbeddable, TSavedObjectAttributes extends SavedObjectAttributes_2 = SavedObjectAttributes_2> extends PersistableState {
+export interface EmbeddableFactory = IEmbeddable, TSavedObjectAttributes extends SavedObjectAttributes_2 = SavedObjectAttributes_2> extends PersistableState {
canCreateNew(): boolean;
create(initialInput: TEmbeddableInput, parent?: IContainer): Promise;
createFromSavedObject(savedObjectId: string, input: Partial, parent?: IContainer): Promise;
@@ -400,7 +401,7 @@ export interface EmbeddableFactory = IEmbeddable, T extends SavedObjectAttributes = SavedObjectAttributes> = Pick, 'create' | 'type' | 'isEditable' | 'getDisplayName'> & Partial, 'createFromSavedObject' | 'isContainerType' | 'getExplicitInput' | 'savedObjectMetaData' | 'canCreateNew' | 'getDefaultInput' | 'telemetry' | 'extract' | 'inject'>>;
+export type EmbeddableFactoryDefinition = IEmbeddable, T extends SavedObjectAttributes = SavedObjectAttributes> = Pick, 'create' | 'type' | 'isEditable' | 'getDisplayName'> & Partial, 'createFromSavedObject' | 'isContainerType' | 'getExplicitInput' | 'savedObjectMetaData' | 'canCreateNew' | 'getDefaultInput' | 'telemetry' | 'extract' | 'inject' | 'migrations'>>;
// Warning: (ae-missing-release-tag) "EmbeddableFactoryNotFoundError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -560,10 +561,11 @@ export interface EmbeddableSetupDependencies {
uiActions: UiActionsSetup;
}
+// Warning: (ae-forgotten-export) The symbol "PersistableStateService" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "EmbeddableStart" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
-export interface EmbeddableStart extends PersistableState {
+export interface EmbeddableStart extends PersistableStateService {
// (undocumented)
EmbeddablePanel: EmbeddablePanelHOC;
// (undocumented)
diff --git a/src/plugins/embeddable/server/plugin.ts b/src/plugins/embeddable/server/plugin.ts
index 1e93561e4d063..6e9186e286491 100644
--- a/src/plugins/embeddable/server/plugin.ts
+++ b/src/plugins/embeddable/server/plugin.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { CoreSetup, CoreStart, Plugin, SavedObjectReference } from 'kibana/server';
+import { CoreSetup, CoreStart, Plugin } from 'kibana/server';
import { identity } from 'lodash';
import {
EmbeddableFactoryRegistry,
@@ -27,12 +27,13 @@ import {
EmbeddableRegistryDefinition,
} from './types';
import {
- extractBaseEmbeddableInput,
- injectBaseEmbeddableInput,
- telemetryBaseEmbeddableInput,
-} from '../common/lib/migrate_base_input';
+ getExtractFunction,
+ getInjectFunction,
+ getMigrateFunction,
+ getTelemetryFunction,
+} from '../common/lib';
import { SerializableState } from '../../kibana_utils/common';
-import { EmbeddableInput } from '../common/types';
+import { EmbeddableStateWithType } from '../common/types';
export interface EmbeddableSetup {
getAttributeService: any;
@@ -52,82 +53,20 @@ export class EmbeddableServerPlugin implements Plugin