mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 11:05:39 -04:00
updating persistable state types (#123340)
This commit is contained in:
parent
cd06e5f5af
commit
c2bd8d127f
15 changed files with 69 additions and 31 deletions
|
@ -84,7 +84,11 @@ const ActionsExplorer = ({ share }: Props) => {
|
||||||
if (!locator) return;
|
if (!locator) return;
|
||||||
let params: HelloLocatorV1Params | HelloLocatorV2Params = savedLink.params;
|
let params: HelloLocatorV1Params | HelloLocatorV2Params = savedLink.params;
|
||||||
if (savedLink.version === '0.0.1') {
|
if (savedLink.version === '0.0.1') {
|
||||||
const migration = locator.migrations['0.0.2'];
|
const migrations =
|
||||||
|
typeof locator.migrations === 'function'
|
||||||
|
? locator.migrations()
|
||||||
|
: locator.migrations || {};
|
||||||
|
const migration = migrations['0.0.2'];
|
||||||
if (migration) {
|
if (migration) {
|
||||||
params = migration(params) as HelloLocatorV2Params;
|
params = migration(params) as HelloLocatorV2Params;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,14 @@
|
||||||
import { getAllMigrations } from './get_all_migrations';
|
import { getAllMigrations } from './get_all_migrations';
|
||||||
|
|
||||||
describe('embeddable getAllMigratons', () => {
|
describe('embeddable getAllMigratons', () => {
|
||||||
const factories = [{ migrations: { '7.11.0': (state: unknown) => state } }];
|
const factories = [
|
||||||
const enhacements = [{ migrations: { '7.12.0': (state: unknown) => state } }];
|
{ migrations: { '7.11.0': (state: unknown) => state } },
|
||||||
|
{ migrations: () => ({ '7.13.0': (state: unknown) => state }) },
|
||||||
|
];
|
||||||
|
const enhacements = [
|
||||||
|
{ migrations: { '7.12.0': (state: unknown) => state } },
|
||||||
|
{ migrations: () => ({ '7.14.0': (state: unknown) => state }) },
|
||||||
|
];
|
||||||
const migrateFn = jest.fn();
|
const migrateFn = jest.fn();
|
||||||
|
|
||||||
test('returns base migrations', () => {
|
test('returns base migrations', () => {
|
||||||
|
@ -19,16 +25,20 @@ describe('embeddable getAllMigratons', () => {
|
||||||
|
|
||||||
test('returns embeddable factory migrations', () => {
|
test('returns embeddable factory migrations', () => {
|
||||||
expect(getAllMigrations(factories, [], migrateFn)).toHaveProperty(['7.11.0']);
|
expect(getAllMigrations(factories, [], migrateFn)).toHaveProperty(['7.11.0']);
|
||||||
|
expect(getAllMigrations(factories, [], migrateFn)).toHaveProperty(['7.13.0']);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('returns enhancement migrations', () => {
|
test('returns enhancement migrations', () => {
|
||||||
const migrations = getAllMigrations([], enhacements, migrateFn);
|
const migrations = getAllMigrations([], enhacements, migrateFn);
|
||||||
expect(migrations).toHaveProperty(['7.12.0']);
|
expect(migrations).toHaveProperty(['7.12.0']);
|
||||||
|
expect(migrations).toHaveProperty(['7.14.0']);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('returns all migrations', () => {
|
test('returns all migrations', () => {
|
||||||
const migrations = getAllMigrations(factories, enhacements, migrateFn);
|
const migrations = getAllMigrations(factories, enhacements, migrateFn);
|
||||||
expect(migrations).toHaveProperty(['7.11.0']);
|
expect(migrations).toHaveProperty(['7.11.0']);
|
||||||
expect(migrations).toHaveProperty(['7.12.0']);
|
expect(migrations).toHaveProperty(['7.12.0']);
|
||||||
|
expect(migrations).toHaveProperty(['7.13.0']);
|
||||||
|
expect(migrations).toHaveProperty(['7.14.0']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -23,14 +23,14 @@ export const getAllMigrations = (
|
||||||
uniqueVersions.add(baseMigrationVersion);
|
uniqueVersions.add(baseMigrationVersion);
|
||||||
}
|
}
|
||||||
for (const factory of factories) {
|
for (const factory of factories) {
|
||||||
Object.keys((factory as PersistableState).migrations).forEach((version) =>
|
const migrations = (factory as PersistableState).migrations;
|
||||||
uniqueVersions.add(version)
|
const factoryMigrations = typeof migrations === 'function' ? migrations() : migrations;
|
||||||
);
|
Object.keys(factoryMigrations).forEach((version) => uniqueVersions.add(version));
|
||||||
}
|
}
|
||||||
for (const enhancement of enhancements) {
|
for (const enhancement of enhancements) {
|
||||||
Object.keys((enhancement as PersistableState).migrations).forEach((version) =>
|
const migrations = (enhancement as PersistableState).migrations;
|
||||||
uniqueVersions.add(version)
|
const enhancementMigrations = typeof migrations === 'function' ? migrations() : migrations;
|
||||||
);
|
Object.keys(enhancementMigrations).forEach((version) => uniqueVersions.add(version));
|
||||||
}
|
}
|
||||||
|
|
||||||
const migrations: MigrateFunctionsObject = {};
|
const migrations: MigrateFunctionsObject = {};
|
||||||
|
|
|
@ -21,8 +21,10 @@ export const getMigrateFunction = (embeddables: CommonEmbeddableStartContract) =
|
||||||
? baseEmbeddableMigrations[version](state)
|
? baseEmbeddableMigrations[version](state)
|
||||||
: state;
|
: state;
|
||||||
|
|
||||||
if (factory?.migrations[version]) {
|
const factoryMigrations =
|
||||||
updatedInput = factory.migrations[version](updatedInput);
|
typeof factory?.migrations === 'function' ? factory?.migrations() : factory?.migrations || {};
|
||||||
|
if (factoryMigrations[version]) {
|
||||||
|
updatedInput = factoryMigrations[version](updatedInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (factory?.isContainerType) {
|
if (factory?.isContainerType) {
|
||||||
|
@ -35,8 +37,12 @@ export const getMigrateFunction = (embeddables: CommonEmbeddableStartContract) =
|
||||||
Object.keys(enhancements).forEach((key) => {
|
Object.keys(enhancements).forEach((key) => {
|
||||||
if (!enhancements[key]) return;
|
if (!enhancements[key]) return;
|
||||||
const enhancementDefinition = embeddables.getEnhancement(key);
|
const enhancementDefinition = embeddables.getEnhancement(key);
|
||||||
const migratedEnhancement = enhancementDefinition?.migrations?.[version]
|
const enchantmentMigrations =
|
||||||
? enhancementDefinition.migrations[version](enhancements[key] as SerializableRecord)
|
typeof enhancementDefinition?.migrations === 'function'
|
||||||
|
? enhancementDefinition?.migrations()
|
||||||
|
: enhancementDefinition?.migrations || {};
|
||||||
|
const migratedEnhancement = enchantmentMigrations[version]
|
||||||
|
? enchantmentMigrations[version](enhancements[key] as SerializableRecord)
|
||||||
: enhancements[key];
|
: enhancements[key];
|
||||||
(updatedInput.enhancements! as Record<string, {}>)[key] = migratedEnhancement;
|
(updatedInput.enhancements! as Record<string, {}>)[key] = migratedEnhancement;
|
||||||
});
|
});
|
||||||
|
|
|
@ -352,11 +352,13 @@ export class Executor<Context extends Record<string, unknown> = Record<string, u
|
||||||
|
|
||||||
private migrate(ast: SerializableRecord, version: string) {
|
private migrate(ast: SerializableRecord, version: string) {
|
||||||
return this.walkAstAndTransform(cloneDeep(ast) as ExpressionAstExpression, (fn, link) => {
|
return this.walkAstAndTransform(cloneDeep(ast) as ExpressionAstExpression, (fn, link) => {
|
||||||
if (!fn.migrations[version]) {
|
const migrations =
|
||||||
|
typeof fn.migrations === 'function' ? fn.migrations() : fn.migrations || {};
|
||||||
|
if (!migrations[version]) {
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fn.migrations[version](link) as ExpressionAstExpression;
|
return migrations[version](link) as ExpressionAstExpression;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { identity } from 'lodash';
|
import { identity } from 'lodash';
|
||||||
import type { SerializableRecord } from '@kbn/utility-types';
|
|
||||||
import { AnyExpressionFunctionDefinition } from './types';
|
import { AnyExpressionFunctionDefinition } from './types';
|
||||||
import { ExpressionFunctionParameter } from './expression_function_parameter';
|
import { ExpressionFunctionParameter } from './expression_function_parameter';
|
||||||
import { ExpressionValue } from '../expression_types/types';
|
import { ExpressionValue } from '../expression_types/types';
|
||||||
import { ExpressionAstFunction } from '../ast';
|
import { ExpressionAstFunction } from '../ast';
|
||||||
import { SavedObjectReference } from '../../../../core/types';
|
import { SavedObjectReference } from '../../../../core/types';
|
||||||
import { PersistableState } from '../../../kibana_utils/common';
|
import {
|
||||||
|
MigrateFunctionsObject,
|
||||||
|
GetMigrationFunctionObjectFn,
|
||||||
|
PersistableState,
|
||||||
|
} from '../../../kibana_utils/common';
|
||||||
|
|
||||||
export class ExpressionFunction implements PersistableState<ExpressionAstFunction['arguments']> {
|
export class ExpressionFunction implements PersistableState<ExpressionAstFunction['arguments']> {
|
||||||
/**
|
/**
|
||||||
|
@ -70,9 +73,7 @@ export class ExpressionFunction implements PersistableState<ExpressionAstFunctio
|
||||||
state: ExpressionAstFunction['arguments'],
|
state: ExpressionAstFunction['arguments'],
|
||||||
references: SavedObjectReference[]
|
references: SavedObjectReference[]
|
||||||
) => ExpressionAstFunction['arguments'];
|
) => ExpressionAstFunction['arguments'];
|
||||||
migrations: {
|
migrations: MigrateFunctionsObject | GetMigrationFunctionObjectFn;
|
||||||
[key: string]: (state: SerializableRecord) => SerializableRecord;
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(functionDefinition: AnyExpressionFunctionDefinition) {
|
constructor(functionDefinition: AnyExpressionFunctionDefinition) {
|
||||||
const {
|
const {
|
||||||
|
|
|
@ -60,6 +60,7 @@ export type {
|
||||||
PersistableStateMigrateFn,
|
PersistableStateMigrateFn,
|
||||||
MigrateFunction,
|
MigrateFunction,
|
||||||
MigrateFunctionsObject,
|
MigrateFunctionsObject,
|
||||||
|
GetMigrationFunctionObjectFn,
|
||||||
PersistableState,
|
PersistableState,
|
||||||
PersistableStateDefinition,
|
PersistableStateDefinition,
|
||||||
} from './persistable_state';
|
} from './persistable_state';
|
||||||
|
|
|
@ -14,6 +14,7 @@ export type {
|
||||||
PersistableStateService,
|
PersistableStateService,
|
||||||
MigrateFunctionsObject,
|
MigrateFunctionsObject,
|
||||||
MigrateFunction,
|
MigrateFunction,
|
||||||
|
GetMigrationFunctionObjectFn,
|
||||||
} from './types';
|
} from './types';
|
||||||
export { migrateToLatest } from './migrate_to_latest';
|
export { migrateToLatest } from './migrate_to_latest';
|
||||||
export { mergeMigrationFunctionMaps } from './merge_migration_function_map';
|
export { mergeMigrationFunctionMaps } from './merge_migration_function_map';
|
||||||
|
|
|
@ -82,9 +82,11 @@ export interface PersistableState<P extends SerializableRecord = SerializableRec
|
||||||
* keyed by the Kibana version using semver, where the version indicates to
|
* keyed by the Kibana version using semver, where the version indicates to
|
||||||
* which version the state will be migrated to.
|
* which version the state will be migrated to.
|
||||||
*/
|
*/
|
||||||
migrations: MigrateFunctionsObject;
|
migrations: MigrateFunctionsObject | GetMigrationFunctionObjectFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type GetMigrationFunctionObjectFn = () => MigrateFunctionsObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection of migrations that a given type of persistable state object has
|
* Collection of migrations that a given type of persistable state object has
|
||||||
* accumulated over time. Migration functions are keyed using semver version
|
* accumulated over time. Migration functions are keyed using semver version
|
||||||
|
|
|
@ -58,7 +58,8 @@ export class LocatorClient implements ILocatorClient {
|
||||||
const migrations: { [locatorId: string]: MigrateFunctionsObject } = {};
|
const migrations: { [locatorId: string]: MigrateFunctionsObject } = {};
|
||||||
|
|
||||||
for (const locator of this.locators.values()) {
|
for (const locator of this.locators.values()) {
|
||||||
migrations[locator.id] = locator.migrations;
|
migrations[locator.id] =
|
||||||
|
typeof locator.migrations === 'function' ? locator.migrations() : locator.migrations;
|
||||||
}
|
}
|
||||||
|
|
||||||
return migrations;
|
return migrations;
|
||||||
|
|
|
@ -60,7 +60,9 @@ export class RedirectManager {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
const migratedParams = migrateToLatest(locator.migrations, {
|
const locatorMigrations =
|
||||||
|
typeof locator.migrations === 'function' ? locator.migrations() : locator.migrations;
|
||||||
|
const migratedParams = migrateToLatest(locatorMigrations, {
|
||||||
state: options.params,
|
state: options.params,
|
||||||
version: options.version,
|
version: options.version,
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,7 +14,8 @@ describe('filters migrations', () => {
|
||||||
const expression = 'filters group="1" group="3" ungrouped=true';
|
const expression = 'filters group="1" group="3" ungrouped=true';
|
||||||
const ast = fromExpression(expression);
|
const ast = fromExpression(expression);
|
||||||
it('8.1.0. Should migrate `filters` expression to `kibana | selectFilter`', () => {
|
it('8.1.0. Should migrate `filters` expression to `kibana | selectFilter`', () => {
|
||||||
const migratedAst = migrations?.['8.1.0'](ast.chain[0]);
|
const migrationObj = typeof migrations === 'function' ? migrations() : migrations || {};
|
||||||
|
const migratedAst = migrationObj['8.1.0'](ast.chain[0]);
|
||||||
expect(migratedAst !== null && typeof migratedAst === 'object').toBeTruthy();
|
expect(migratedAst !== null && typeof migratedAst === 'object').toBeTruthy();
|
||||||
expect(migratedAst.type).toBe('expression');
|
expect(migratedAst.type).toBe('expression');
|
||||||
expect(Array.isArray(migratedAst.chain)).toBeTruthy();
|
expect(Array.isArray(migratedAst.chain)).toBeTruthy();
|
||||||
|
|
|
@ -52,13 +52,13 @@ export interface CreateCommentsMigrationsDeps {
|
||||||
export const createCommentsMigrations = (
|
export const createCommentsMigrations = (
|
||||||
migrationDeps: CreateCommentsMigrationsDeps
|
migrationDeps: CreateCommentsMigrationsDeps
|
||||||
): SavedObjectMigrationMap => {
|
): SavedObjectMigrationMap => {
|
||||||
|
const lensMigrations = migrationDeps.lensEmbeddableFactory().migrations;
|
||||||
|
const lensMigrationObject =
|
||||||
|
typeof lensMigrations === 'function' ? lensMigrations() : lensMigrations || {};
|
||||||
const embeddableMigrations = mapValues<
|
const embeddableMigrations = mapValues<
|
||||||
MigrateFunctionsObject,
|
MigrateFunctionsObject,
|
||||||
SavedObjectMigrationFn<{ comment?: string }>
|
SavedObjectMigrationFn<{ comment?: string }>
|
||||||
>(
|
>(lensMigrationObject, migrateByValueLensVisualizations) as MigrateFunctionsObject;
|
||||||
migrationDeps.lensEmbeddableFactory().migrations,
|
|
||||||
migrateByValueLensVisualizations
|
|
||||||
) as MigrateFunctionsObject;
|
|
||||||
|
|
||||||
const commentsMigrations = {
|
const commentsMigrations = {
|
||||||
'7.11.0': (
|
'7.11.0': (
|
||||||
|
|
|
@ -52,7 +52,11 @@ describe('embeddable migrations', () => {
|
||||||
},
|
},
|
||||||
})()?.migrations;
|
})()?.migrations;
|
||||||
|
|
||||||
const migratedLensDoc = embeddableMigrationVersions?.[migrationVersion](lensVisualizationDoc);
|
const migrations =
|
||||||
|
typeof embeddableMigrationVersions === 'function'
|
||||||
|
? embeddableMigrationVersions()
|
||||||
|
: embeddableMigrationVersions || {};
|
||||||
|
const migratedLensDoc = migrations[migrationVersion](lensVisualizationDoc);
|
||||||
|
|
||||||
expect(migratedLensDoc).toEqual({
|
expect(migratedLensDoc).toEqual({
|
||||||
attributes: {
|
attributes: {
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { UiComponent, CollectConfigProps } from 'src/plugins/kibana_utils/public';
|
import type { UiComponent, CollectConfigProps } from 'src/plugins/kibana_utils/public';
|
||||||
import type { MigrateFunctionsObject } from 'src/plugins/kibana_utils/common';
|
import type {
|
||||||
|
MigrateFunctionsObject,
|
||||||
|
GetMigrationFunctionObjectFn,
|
||||||
|
} from 'src/plugins/kibana_utils/common';
|
||||||
import { uiToReactComponent } from '../../../../../src/plugins/kibana_react/public';
|
import { uiToReactComponent } from '../../../../../src/plugins/kibana_react/public';
|
||||||
import type {
|
import type {
|
||||||
UiActionsPresentable as Presentable,
|
UiActionsPresentable as Presentable,
|
||||||
|
@ -51,7 +54,7 @@ export class ActionFactory<
|
||||||
public readonly ReactCollectConfig: React.FC<CollectConfigProps<Config, FactoryContext>>;
|
public readonly ReactCollectConfig: React.FC<CollectConfigProps<Config, FactoryContext>>;
|
||||||
public readonly createConfig: (context: FactoryContext) => Config;
|
public readonly createConfig: (context: FactoryContext) => Config;
|
||||||
public readonly isConfigValid: (config: Config, context: FactoryContext) => boolean;
|
public readonly isConfigValid: (config: Config, context: FactoryContext) => boolean;
|
||||||
public readonly migrations: MigrateFunctionsObject;
|
public readonly migrations: MigrateFunctionsObject | GetMigrationFunctionObjectFn;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected readonly def: ActionFactoryDefinition<Config, ExecutionContext, FactoryContext>,
|
protected readonly def: ActionFactoryDefinition<Config, ExecutionContext, FactoryContext>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue