From 2b3787ad2c5cb227d751692b1f6954c53200076a Mon Sep 17 00:00:00 2001 From: Peter Pisljar Date: Thu, 5 Nov 2020 07:03:23 +0100 Subject: [PATCH] Embeddables/migrations (#82296) --- ...ins-embeddable-public.embeddablefactory.md | 2 +- ...able-public.embeddablefactorydefinition.md | 2 +- ...ugins-embeddable-public.embeddablestart.md | 2 +- ...ble-server.embeddableregistrydefinition.md | 2 +- ...gin-plugins-expressions-public.executor.md | 3 +- ...essions-public.executor.migratetolatest.md | 23 ---- ...s-expressions-public.expressionsservice.md | 5 +- ...sions-public.expressionsservice.migrate.md | 2 +- ...blic.expressionsservice.migratetolatest.md | 13 --- ...gin-plugins-expressions-server.executor.md | 3 +- ...essions-server.executor.migratetolatest.md | 23 ---- src/plugins/embeddable/common/lib/extract.ts | 54 +++++++++ src/plugins/embeddable/common/lib/index.ts | 24 ++++ src/plugins/embeddable/common/lib/inject.ts | 46 ++++++++ src/plugins/embeddable/common/lib/migrate.ts | 47 ++++++++ .../common/lib/migrate_base_input.ts | 11 +- .../embeddable/common/lib/telemetry.ts | 41 +++++++ src/plugins/embeddable/common/types.ts | 7 ++ .../default_embeddable_factory_provider.ts | 6 +- .../lib/embeddables/embeddable_factory.ts | 3 +- .../embeddable_factory_definition.ts | 1 + src/plugins/embeddable/public/mocks.tsx | 1 + src/plugins/embeddable/public/plugin.test.ts | 15 +++ src/plugins/embeddable/public/plugin.tsx | 99 ++++------------- src/plugins/embeddable/public/public.api.md | 8 +- src/plugins/embeddable/server/plugin.ts | 103 ++++-------------- src/plugins/embeddable/server/server.api.md | 5 +- src/plugins/embeddable/server/types.ts | 9 +- .../common/executor/executor.test.ts | 11 -- .../expressions/common/executor/executor.ts | 30 +---- .../common/service/expressions_services.ts | 14 +-- src/plugins/expressions/public/public.api.md | 10 +- src/plugins/expressions/server/server.api.md | 7 +- src/plugins/kibana_utils/.eslintrc.json | 5 + .../common/persistable_state/index.ts | 43 ++++++-- .../public/dynamic_actions/action_factory.ts | 1 + .../ui_actions_enhanced/server/plugin.ts | 1 + 37 files changed, 364 insertions(+), 318 deletions(-) delete mode 100644 docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.executor.migratetolatest.md delete mode 100644 docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionsservice.migratetolatest.md delete mode 100644 docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.executor.migratetolatest.md create mode 100644 src/plugins/embeddable/common/lib/extract.ts create mode 100644 src/plugins/embeddable/common/lib/index.ts create mode 100644 src/plugins/embeddable/common/lib/inject.ts create mode 100644 src/plugins/embeddable/common/lib/migrate.ts create mode 100644 src/plugins/embeddable/common/lib/telemetry.ts create mode 100644 src/plugins/kibana_utils/.eslintrc.json diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.md index d543cf3d096df..b355acd0567a8 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactory.md @@ -9,7 +9,7 @@ EmbeddableFactories create and initialize an embeddable instance Signature: ```typescript -export interface EmbeddableFactory = IEmbeddable, TSavedObjectAttributes extends SavedObjectAttributes = SavedObjectAttributes> extends PersistableState +export interface EmbeddableFactory = IEmbeddable, TSavedObjectAttributes extends SavedObjectAttributes = SavedObjectAttributes> extends PersistableState ``` ## Properties diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorydefinition.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorydefinition.md index 4e342d3cf73a1..6ecb88e7c017e 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorydefinition.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablefactorydefinition.md @@ -7,5 +7,5 @@ Signature: ```typescript -export declare type EmbeddableFactoryDefinition = IEmbeddable, T extends SavedObjectAttributes = SavedObjectAttributes> = Pick, 'create' | 'type' | 'isEditable' | 'getDisplayName'> & Partial, 'createFromSavedObject' | 'isContainerType' | 'getExplicitInput' | 'savedObjectMetaData' | 'canCreateNew' | 'getDefaultInput' | 'telemetry' | 'extract' | 'inject'>>; +export declare type EmbeddableFactoryDefinition = IEmbeddable, T extends SavedObjectAttributes = SavedObjectAttributes> = Pick, 'create' | 'type' | 'isEditable' | 'getDisplayName'> & Partial, 'createFromSavedObject' | 'isContainerType' | 'getExplicitInput' | 'savedObjectMetaData' | 'canCreateNew' | 'getDefaultInput' | 'telemetry' | 'extract' | 'inject' | 'migrations'>>; ``` diff --git a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md index 541575566d3f7..f500196d850a2 100644 --- a/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md +++ b/docs/development/plugins/embeddable/public/kibana-plugin-plugins-embeddable-public.embeddablestart.md @@ -7,7 +7,7 @@ Signature: ```typescript -export interface EmbeddableStart extends PersistableState +export interface EmbeddableStart extends PersistableStateService ``` ## 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 { } public start(core: CoreStart) { - return { - telemetry: this.telemetry, - extract: this.extract, - inject: this.inject, + const commonContract = { + getEmbeddableFactory: this.getEmbeddableFactory, + getEnhancement: this.getEnhancement, }; - } - - public stop() {} - - private telemetry = (state: EmbeddableInput, telemetryData: Record = {}) => { - 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, + telemetry: getTelemetryFunction(commonContract), + extract: getExtractFunction(commonContract), + inject: getInjectFunction(commonContract), + migrate: getMigrateFunction(commonContract), }; - }; - - 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; - }; + public stop() {} private registerEnhancement = (enhancement: EnhancementRegistryDefinition) => { if (this.enhancements.has(enhancement.id)) { @@ -142,6 +81,7 @@ export class EmbeddableServerPlugin implements Plugin { ((state: SerializableState) => { return { state, references: [] }; }), + migrations: enhancement.migrations || {}, }); }; @@ -154,6 +94,7 @@ export class EmbeddableServerPlugin implements Plugin { extract: (state: SerializableState) => { return { state, references: [] }; }, + migrations: {}, } ); }; @@ -168,7 +109,8 @@ export class EmbeddableServerPlugin implements Plugin { id: factory.id, telemetry: factory.telemetry || (() => ({})), inject: factory.inject || identity, - extract: factory.extract || ((state: EmbeddableInput) => ({ state, references: [] })), + extract: factory.extract || ((state: EmbeddableStateWithType) => ({ state, references: [] })), + migrations: factory.migrations || {}, }); }; @@ -177,10 +119,11 @@ export class EmbeddableServerPlugin implements Plugin { this.embeddableFactories.get(embeddableFactoryId) || { id: 'unknown', telemetry: () => ({}), - inject: (state: EmbeddableInput) => state, - extract: (state: EmbeddableInput) => { + inject: (state: EmbeddableStateWithType) => state, + extract: (state: EmbeddableStateWithType) => { return { state, references: [] }; }, + migrations: {}, } ); }; diff --git a/src/plugins/embeddable/server/server.api.md b/src/plugins/embeddable/server/server.api.md index d051793382ab7..87f7d76cffaa8 100644 --- a/src/plugins/embeddable/server/server.api.md +++ b/src/plugins/embeddable/server/server.api.md @@ -7,14 +7,13 @@ import { CoreSetup } from 'kibana/server'; import { CoreStart } from 'kibana/server'; import { Plugin } from 'kibana/server'; -import { SavedObjectReference as SavedObjectReference_2 } from 'kibana/server'; -// Warning: (ae-forgotten-export) The symbol "EmbeddableInput" 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-forgotten-export) The symbol "PersistableStateDefinition" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "EmbeddableRegistryDefinition" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export interface EmbeddableRegistryDefinition

extends PersistableStateDefinition

{ +export interface EmbeddableRegistryDefinition

extends PersistableStateDefinition

{ // (undocumented) id: string; } diff --git a/src/plugins/embeddable/server/types.ts b/src/plugins/embeddable/server/types.ts index 64f9325dad3cb..388d4feb66104 100644 --- a/src/plugins/embeddable/server/types.ts +++ b/src/plugins/embeddable/server/types.ts @@ -22,7 +22,7 @@ import { PersistableStateDefinition, SerializableState, } from '../../kibana_utils/common'; -import { EmbeddableInput } from '../common/types'; +import { EmbeddableStateWithType } from '../common/types'; export type EmbeddableFactoryRegistry = Map; export type EnhancementsRegistry = Map; @@ -37,12 +37,13 @@ export interface EnhancementRegistryItem

- extends PersistableStateDefinition

{ +export interface EmbeddableRegistryDefinition< + P extends EmbeddableStateWithType = EmbeddableStateWithType +> extends PersistableStateDefinition

{ id: string; } -export interface EmbeddableRegistryItem

+export interface EmbeddableRegistryItem

extends PersistableState

{ id: string; } diff --git a/src/plugins/expressions/common/executor/executor.test.ts b/src/plugins/expressions/common/executor/executor.test.ts index 308d6f7e71814..0c1fdf9891fca 100644 --- a/src/plugins/expressions/common/executor/executor.test.ts +++ b/src/plugins/expressions/common/executor/executor.test.ts @@ -214,16 +214,5 @@ describe('Executor', () => { expect(migrateFn).toBeCalledTimes(5); }); }); - - describe('.migrateToLatest', () => { - test('calls extract function for every expression function in expression', () => { - migrateFn.mockClear(); - executor.migrateToLatest( - parseExpression('foo bar="baz" | foo bar={foo bar="baz" | foo bar={foo bar="baz"}}'), - '7.10.0' - ); - expect(migrateFn).toBeCalledTimes(10); - }); - }); }); }); diff --git a/src/plugins/expressions/common/executor/executor.ts b/src/plugins/expressions/common/executor/executor.ts index 19fc4cf5a14a2..ca631600b1083 100644 --- a/src/plugins/expressions/common/executor/executor.ts +++ b/src/plugins/expressions/common/executor/executor.ts @@ -32,7 +32,7 @@ import { typeSpecs } from '../expression_types/specs'; import { functionSpecs } from '../expression_functions/specs'; import { getByAlias } from '../util'; import { SavedObjectReference } from '../../../../core/types'; -import { PersistableState, SerializableState } from '../../../kibana_utils/common'; +import { PersistableStateService, SerializableState } from '../../../kibana_utils/common'; import { ExpressionExecutionParams } from '../service'; export interface ExpressionExecOptions { @@ -88,22 +88,8 @@ export class FunctionsRegistry implements IRegistry { } } -const semverGte = (semver1: string, semver2: string) => { - const regex = /^([0-9]+)\.([0-9]+)\.([0-9]+)$/; - const matches1 = regex.exec(semver1) as RegExpMatchArray; - const matches2 = regex.exec(semver2) as RegExpMatchArray; - - const [, major1, minor1, patch1] = matches1; - const [, major2, minor2, patch2] = matches2; - - return ( - major1 > major2 || - (major1 === major2 && (minor1 > minor2 || (minor1 === minor2 && patch1 >= patch2))) - ); -}; - export class Executor = Record> - implements PersistableState { + implements PersistableStateService { static createWithDefaults = Record>( state?: ExecutorState ): Executor { @@ -272,18 +258,6 @@ export class Executor = Record { - for (const key of Object.keys(fn.migrations)) { - if (semverGte(key, version)) { - const updatedAst = fn.migrations[key](link) as ExpressionAstFunction; - link.arguments = updatedAst.arguments; - link.type = updatedAst.type; - } - } - }); - } - public fork(): Executor { const initialState = this.state.get(); const fork = new Executor(initialState); diff --git a/src/plugins/expressions/common/service/expressions_services.ts b/src/plugins/expressions/common/service/expressions_services.ts index 0f898563c3d0e..01289ca1ae57a 100644 --- a/src/plugins/expressions/common/service/expressions_services.ts +++ b/src/plugins/expressions/common/service/expressions_services.ts @@ -24,7 +24,7 @@ import { ExecutionContract } from '../execution/execution_contract'; import { AnyExpressionTypeDefinition } from '../expression_types'; import { AnyExpressionFunctionDefinition } from '../expression_functions'; import { SavedObjectReference } from '../../../../core/types'; -import { PersistableState, SerializableState } from '../../../kibana_utils/common'; +import { PersistableStateService, SerializableState } from '../../../kibana_utils/common'; import { Adapters } from '../../../inspector/common/adapters'; import { ExecutionContextSearch } from '../execution'; @@ -171,7 +171,7 @@ export interface ExpressionServiceParams { * * so that JSDoc appears in developers IDE when they use those `plugins.expressions.registerFunction(`. */ -export class ExpressionsService implements PersistableState { +export class ExpressionsService implements PersistableStateService { public readonly executor: Executor; public readonly renderers: ExpressionRendererRegistry; @@ -313,16 +313,6 @@ export class ExpressionsService implements PersistableState { - return this.executor.migrateToLatest(state, version); - }; - /** * Returns Kibana Platform *setup* life-cycle contract. Useful to return the * same contract on server-side and browser-side. diff --git a/src/plugins/expressions/public/public.api.md b/src/plugins/expressions/public/public.api.md index 454c3030aa072..e6bff703aadcd 100644 --- a/src/plugins/expressions/public/public.api.md +++ b/src/plugins/expressions/public/public.api.md @@ -187,11 +187,11 @@ export interface ExecutionState extends ExecutorState state: 'not-started' | 'pending' | 'result' | 'error'; } -// Warning: (ae-forgotten-export) The symbol "PersistableState" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "PersistableStateService" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Executor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export class Executor = Record> implements PersistableState { +export class Executor = Record> implements PersistableStateService { constructor(state?: ExecutorState); // (undocumented) get context(): Record; @@ -227,8 +227,6 @@ export class Executor = Record AnyExpressionFunctionDefinition)): void; // (undocumented) registerType(typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)): void; @@ -327,6 +325,7 @@ export interface ExpressionExecutor { interpreter: ExpressionInterpreter; } +// Warning: (ae-forgotten-export) The symbol "PersistableState" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ExpressionFunction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -581,7 +580,7 @@ export { ExpressionsPublicPlugin as Plugin } // Warning: (ae-missing-release-tag) "ExpressionsService" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export class ExpressionsService implements PersistableState { +export class ExpressionsService implements PersistableStateService { // Warning: (ae-forgotten-export) The symbol "ExpressionServiceParams" needs to be exported by the entry point index.d.ts constructor({ executor, renderers, }?: ExpressionServiceParams); // (undocumented) @@ -605,7 +604,6 @@ export class ExpressionsService implements PersistableState ReturnType; readonly inject: (state: ExpressionAstExpression, references: SavedObjectReference[]) => ExpressionAstExpression; readonly migrate: (state: SerializableState, version: string) => ExpressionAstExpression; - readonly migrateToLatest: (state: unknown, version: string) => ExpressionAstExpression; readonly registerFunction: (functionDefinition: AnyExpressionFunctionDefinition | (() => AnyExpressionFunctionDefinition)) => void; // (undocumented) readonly registerRenderer: (definition: AnyExpressionRenderDefinition | (() => AnyExpressionRenderDefinition)) => void; diff --git a/src/plugins/expressions/server/server.api.md b/src/plugins/expressions/server/server.api.md index 742322b1b5a48..27a3193bf7894 100644 --- a/src/plugins/expressions/server/server.api.md +++ b/src/plugins/expressions/server/server.api.md @@ -169,11 +169,11 @@ export interface ExecutionState extends ExecutorState state: 'not-started' | 'pending' | 'result' | 'error'; } -// Warning: (ae-forgotten-export) The symbol "PersistableState" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "PersistableStateService" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Executor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export class Executor = Record> implements PersistableState { +export class Executor = Record> implements PersistableStateService { constructor(state?: ExecutorState); // (undocumented) get context(): Record; @@ -209,8 +209,6 @@ export class Executor = Record AnyExpressionFunctionDefinition)): void; // (undocumented) registerType(typeDefinition: AnyExpressionTypeDefinition | (() => AnyExpressionTypeDefinition)): void; @@ -299,6 +297,7 @@ export interface ExpressionAstFunctionBuilder = (state: FromVersion) => ToVersion; -export interface PersistableState

{ +export type MigrateFunctionsObject = { + [key: string]: MigrateFunction; +}; + +export interface PersistableStateService

{ /** * function to extract telemetry information * @param state @@ -65,16 +68,36 @@ export interface PersistableState

SerializableState; + migrate: (state: SerializableState, version: string) => SerializableState; } -export type PersistableStateDefinition

= Partial< - Omit, 'migrate'> -> & { +export interface PersistableState

{ + /** + * function to extract telemetry information + * @param state + * @param collector + */ + telemetry: (state: P, collector: Record) => Record; + /** + * inject function receives state and a list of references and should return state with references injected + * default is identity function + * @param state + * @param references + */ + inject: (state: P, references: SavedObjectReference[]) => P; + /** + * extract function receives state and should return state with references extracted and array of references + * default returns same state with empty reference array + * @param state + */ + extract: (state: P) => { state: P; references: SavedObjectReference[] }; + /** * list of all migrations per semver */ - migrations?: { - [key: string]: MigrateFunction; - }; -}; + migrations: MigrateFunctionsObject; +} + +export type PersistableStateDefinition

= Partial< + PersistableState

+>; diff --git a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts index 57c8733ed44fc..a9c498c0210db 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts @@ -67,6 +67,7 @@ export class ActionFactory< public readonly ReactCollectConfig = uiToReactComponent(this.CollectConfig); public readonly createConfig = this.def.createConfig; public readonly isConfigValid = this.def.isConfigValid; + public readonly migrations = this.def.migrations || {}; public getIconType(context: FactoryContext): string | undefined { if (!this.def.getIconType) return undefined; diff --git a/x-pack/plugins/ui_actions_enhanced/server/plugin.ts b/x-pack/plugins/ui_actions_enhanced/server/plugin.ts index 0a61c917a2c5c..d6d18848be4de 100644 --- a/x-pack/plugins/ui_actions_enhanced/server/plugin.ts +++ b/x-pack/plugins/ui_actions_enhanced/server/plugin.ts @@ -61,6 +61,7 @@ export class AdvancedUiActionsPublicPlugin ((state: SerializedEvent) => { return { state, references: [] }; }), + migrations: definition.migrations || {}, }); };