updating persistable state types (#123340)

This commit is contained in:
Peter Pisljar 2022-01-25 18:58:55 +01:00 committed by GitHub
parent cd06e5f5af
commit c2bd8d127f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 69 additions and 31 deletions

View file

@ -84,7 +84,11 @@ const ActionsExplorer = ({ share }: Props) => {
if (!locator) return;
let params: HelloLocatorV1Params | HelloLocatorV2Params = savedLink.params;
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) {
params = migration(params) as HelloLocatorV2Params;
}

View file

@ -9,8 +9,14 @@
import { getAllMigrations } from './get_all_migrations';
describe('embeddable getAllMigratons', () => {
const factories = [{ migrations: { '7.11.0': (state: unknown) => state } }];
const enhacements = [{ migrations: { '7.12.0': (state: unknown) => state } }];
const factories = [
{ 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();
test('returns base migrations', () => {
@ -19,16 +25,20 @@ describe('embeddable getAllMigratons', () => {
test('returns embeddable factory migrations', () => {
expect(getAllMigrations(factories, [], migrateFn)).toHaveProperty(['7.11.0']);
expect(getAllMigrations(factories, [], migrateFn)).toHaveProperty(['7.13.0']);
});
test('returns enhancement migrations', () => {
const migrations = getAllMigrations([], enhacements, migrateFn);
expect(migrations).toHaveProperty(['7.12.0']);
expect(migrations).toHaveProperty(['7.14.0']);
});
test('returns all migrations', () => {
const migrations = getAllMigrations(factories, enhacements, migrateFn);
expect(migrations).toHaveProperty(['7.11.0']);
expect(migrations).toHaveProperty(['7.12.0']);
expect(migrations).toHaveProperty(['7.13.0']);
expect(migrations).toHaveProperty(['7.14.0']);
});
});

View file

@ -23,14 +23,14 @@ export const getAllMigrations = (
uniqueVersions.add(baseMigrationVersion);
}
for (const factory of factories) {
Object.keys((factory as PersistableState).migrations).forEach((version) =>
uniqueVersions.add(version)
);
const migrations = (factory as PersistableState).migrations;
const factoryMigrations = typeof migrations === 'function' ? migrations() : migrations;
Object.keys(factoryMigrations).forEach((version) => uniqueVersions.add(version));
}
for (const enhancement of enhancements) {
Object.keys((enhancement as PersistableState).migrations).forEach((version) =>
uniqueVersions.add(version)
);
const migrations = (enhancement as PersistableState).migrations;
const enhancementMigrations = typeof migrations === 'function' ? migrations() : migrations;
Object.keys(enhancementMigrations).forEach((version) => uniqueVersions.add(version));
}
const migrations: MigrateFunctionsObject = {};

View file

@ -21,8 +21,10 @@ export const getMigrateFunction = (embeddables: CommonEmbeddableStartContract) =
? baseEmbeddableMigrations[version](state)
: state;
if (factory?.migrations[version]) {
updatedInput = factory.migrations[version](updatedInput);
const factoryMigrations =
typeof factory?.migrations === 'function' ? factory?.migrations() : factory?.migrations || {};
if (factoryMigrations[version]) {
updatedInput = factoryMigrations[version](updatedInput);
}
if (factory?.isContainerType) {
@ -35,8 +37,12 @@ export const getMigrateFunction = (embeddables: CommonEmbeddableStartContract) =
Object.keys(enhancements).forEach((key) => {
if (!enhancements[key]) return;
const enhancementDefinition = embeddables.getEnhancement(key);
const migratedEnhancement = enhancementDefinition?.migrations?.[version]
? enhancementDefinition.migrations[version](enhancements[key] as SerializableRecord)
const enchantmentMigrations =
typeof enhancementDefinition?.migrations === 'function'
? enhancementDefinition?.migrations()
: enhancementDefinition?.migrations || {};
const migratedEnhancement = enchantmentMigrations[version]
? enchantmentMigrations[version](enhancements[key] as SerializableRecord)
: enhancements[key];
(updatedInput.enhancements! as Record<string, {}>)[key] = migratedEnhancement;
});

View file

@ -352,11 +352,13 @@ export class Executor<Context extends Record<string, unknown> = Record<string, u
private migrate(ast: SerializableRecord, version: string) {
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 fn.migrations[version](link) as ExpressionAstExpression;
return migrations[version](link) as ExpressionAstExpression;
});
}

View file

@ -7,13 +7,16 @@
*/
import { identity } from 'lodash';
import type { SerializableRecord } from '@kbn/utility-types';
import { AnyExpressionFunctionDefinition } from './types';
import { ExpressionFunctionParameter } from './expression_function_parameter';
import { ExpressionValue } from '../expression_types/types';
import { ExpressionAstFunction } from '../ast';
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']> {
/**
@ -70,9 +73,7 @@ export class ExpressionFunction implements PersistableState<ExpressionAstFunctio
state: ExpressionAstFunction['arguments'],
references: SavedObjectReference[]
) => ExpressionAstFunction['arguments'];
migrations: {
[key: string]: (state: SerializableRecord) => SerializableRecord;
};
migrations: MigrateFunctionsObject | GetMigrationFunctionObjectFn;
constructor(functionDefinition: AnyExpressionFunctionDefinition) {
const {

View file

@ -60,6 +60,7 @@ export type {
PersistableStateMigrateFn,
MigrateFunction,
MigrateFunctionsObject,
GetMigrationFunctionObjectFn,
PersistableState,
PersistableStateDefinition,
} from './persistable_state';

View file

@ -14,6 +14,7 @@ export type {
PersistableStateService,
MigrateFunctionsObject,
MigrateFunction,
GetMigrationFunctionObjectFn,
} from './types';
export { migrateToLatest } from './migrate_to_latest';
export { mergeMigrationFunctionMaps } from './merge_migration_function_map';

View file

@ -82,9 +82,11 @@ export interface PersistableState<P extends SerializableRecord = SerializableRec
* keyed by the Kibana version using semver, where the version indicates 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
* accumulated over time. Migration functions are keyed using semver version

View file

@ -58,7 +58,8 @@ export class LocatorClient implements ILocatorClient {
const migrations: { [locatorId: string]: MigrateFunctionsObject } = {};
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;

View file

@ -60,7 +60,9 @@ export class RedirectManager {
throw error;
}
const migratedParams = migrateToLatest(locator.migrations, {
const locatorMigrations =
typeof locator.migrations === 'function' ? locator.migrations() : locator.migrations;
const migratedParams = migrateToLatest(locatorMigrations, {
state: options.params,
version: options.version,
});

View file

@ -14,7 +14,8 @@ describe('filters migrations', () => {
const expression = 'filters group="1" group="3" ungrouped=true';
const ast = fromExpression(expression);
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.type).toBe('expression');
expect(Array.isArray(migratedAst.chain)).toBeTruthy();

View file

@ -52,13 +52,13 @@ export interface CreateCommentsMigrationsDeps {
export const createCommentsMigrations = (
migrationDeps: CreateCommentsMigrationsDeps
): SavedObjectMigrationMap => {
const lensMigrations = migrationDeps.lensEmbeddableFactory().migrations;
const lensMigrationObject =
typeof lensMigrations === 'function' ? lensMigrations() : lensMigrations || {};
const embeddableMigrations = mapValues<
MigrateFunctionsObject,
SavedObjectMigrationFn<{ comment?: string }>
>(
migrationDeps.lensEmbeddableFactory().migrations,
migrateByValueLensVisualizations
) as MigrateFunctionsObject;
>(lensMigrationObject, migrateByValueLensVisualizations) as MigrateFunctionsObject;
const commentsMigrations = {
'7.11.0': (

View file

@ -52,7 +52,11 @@ describe('embeddable migrations', () => {
},
})()?.migrations;
const migratedLensDoc = embeddableMigrationVersions?.[migrationVersion](lensVisualizationDoc);
const migrations =
typeof embeddableMigrationVersions === 'function'
? embeddableMigrationVersions()
: embeddableMigrationVersions || {};
const migratedLensDoc = migrations[migrationVersion](lensVisualizationDoc);
expect(migratedLensDoc).toEqual({
attributes: {

View file

@ -6,7 +6,10 @@
*/
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 type {
UiActionsPresentable as Presentable,
@ -51,7 +54,7 @@ export class ActionFactory<
public readonly ReactCollectConfig: React.FC<CollectConfigProps<Config, FactoryContext>>;
public readonly createConfig: (context: FactoryContext) => Config;
public readonly isConfigValid: (config: Config, context: FactoryContext) => boolean;
public readonly migrations: MigrateFunctionsObject;
public readonly migrations: MigrateFunctionsObject | GetMigrationFunctionObjectFn;
constructor(
protected readonly def: ActionFactoryDefinition<Config, ExecutionContext, FactoryContext>,