mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[CM] Improve CRUD & RPC interfaces (#154150)
This commit is contained in:
parent
5b250268e7
commit
56c28af1f5
43 changed files with 672 additions and 372 deletions
|
@ -88,7 +88,6 @@ const searchSchemas = getOptionalInOutSchemas({
|
|||
in: schema.maybe(
|
||||
schema.object(
|
||||
{
|
||||
query: schema.maybe(versionableObjectSchema),
|
||||
options: schema.maybe(versionableObjectSchema),
|
||||
},
|
||||
{ unknowns: 'forbid' }
|
||||
|
|
|
@ -179,7 +179,6 @@ describe('CM services getTransforms()', () => {
|
|||
...getVersionnableObjectTests('delete.in.options'),
|
||||
...getVersionnableObjectTests('delete.out.result'),
|
||||
...getVersionnableObjectTests('search.in.options'),
|
||||
...getVersionnableObjectTests('search.in.query'),
|
||||
...getVersionnableObjectTests('search.out.result'),
|
||||
].forEach(({ definitions, expected, ref, error = 'Invalid services definition.' }: any) => {
|
||||
test(`validate: ${ref}`, () => {
|
||||
|
@ -239,7 +238,6 @@ describe('CM services getTransforms()', () => {
|
|||
'update.out.result',
|
||||
'delete.in.options',
|
||||
'delete.out.result',
|
||||
'search.in.query',
|
||||
'search.in.options',
|
||||
'search.out.result',
|
||||
].sort()
|
||||
|
|
|
@ -32,7 +32,6 @@ const serviceObjectPaths = [
|
|||
'update.out.result',
|
||||
'delete.in.options',
|
||||
'delete.out.result',
|
||||
'search.in.query',
|
||||
'search.in.options',
|
||||
'search.out.result',
|
||||
];
|
||||
|
@ -171,7 +170,6 @@ const getDefaultServiceTransforms = (): ServiceTransforms => ({
|
|||
search: {
|
||||
in: {
|
||||
options: getDefaultTransforms(),
|
||||
query: getDefaultTransforms(),
|
||||
},
|
||||
out: {
|
||||
result: getDefaultTransforms(),
|
||||
|
|
|
@ -11,53 +11,52 @@ import type { ObjectTransforms, Version, VersionableObject } from './types';
|
|||
export interface ServicesDefinition {
|
||||
get?: {
|
||||
in?: {
|
||||
options?: VersionableObject;
|
||||
options?: VersionableObject<any, any, any, any>;
|
||||
};
|
||||
out?: {
|
||||
result?: VersionableObject;
|
||||
result?: VersionableObject<any, any, any, any>;
|
||||
};
|
||||
};
|
||||
bulkGet?: {
|
||||
in?: {
|
||||
options?: VersionableObject;
|
||||
options?: VersionableObject<any, any, any, any>;
|
||||
};
|
||||
out?: {
|
||||
result?: VersionableObject;
|
||||
result?: VersionableObject<any, any, any, any>;
|
||||
};
|
||||
};
|
||||
create?: {
|
||||
in?: {
|
||||
data?: VersionableObject;
|
||||
options?: VersionableObject;
|
||||
data?: VersionableObject<any, any, any, any>;
|
||||
options?: VersionableObject<any, any, any, any>;
|
||||
};
|
||||
out?: {
|
||||
result?: VersionableObject;
|
||||
result?: VersionableObject<any, any, any, any>;
|
||||
};
|
||||
};
|
||||
update?: {
|
||||
in?: {
|
||||
data?: VersionableObject;
|
||||
options?: VersionableObject;
|
||||
data?: VersionableObject<any, any, any, any>;
|
||||
options?: VersionableObject<any, any, any, any>;
|
||||
};
|
||||
out?: {
|
||||
result?: VersionableObject;
|
||||
result?: VersionableObject<any, any, any, any>;
|
||||
};
|
||||
};
|
||||
delete?: {
|
||||
in?: {
|
||||
options?: VersionableObject;
|
||||
options?: VersionableObject<any, any, any, any>;
|
||||
};
|
||||
out?: {
|
||||
result?: VersionableObject;
|
||||
result?: VersionableObject<any, any, any, any>;
|
||||
};
|
||||
};
|
||||
search?: {
|
||||
in?: {
|
||||
query?: VersionableObject;
|
||||
options?: VersionableObject;
|
||||
options?: VersionableObject<any, any, any, any>;
|
||||
};
|
||||
out?: {
|
||||
result?: VersionableObject;
|
||||
result?: VersionableObject<any, any, any, any>;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -107,7 +106,6 @@ export interface ServiceTransforms {
|
|||
};
|
||||
search: {
|
||||
in: {
|
||||
query: ObjectTransforms;
|
||||
options: ObjectTransforms;
|
||||
};
|
||||
out: {
|
||||
|
|
|
@ -25,7 +25,7 @@ const v1Tv2Transform = jest.fn((v1: FooV1): FooV2 => {
|
|||
return { firstName, lastName };
|
||||
});
|
||||
|
||||
const fooDefV1: VersionableObject = {
|
||||
const fooDefV1: VersionableObject<any, any, any, any> = {
|
||||
schema: schema.object({
|
||||
fullName: schema.string({ minLength: 1 }),
|
||||
}),
|
||||
|
@ -43,7 +43,7 @@ const v2Tv1Transform = jest.fn((v2: FooV2): FooV1 => {
|
|||
};
|
||||
});
|
||||
|
||||
const fooDefV2: VersionableObject = {
|
||||
const fooDefV2: VersionableObject<any, any, any, any> = {
|
||||
schema: schema.object({
|
||||
firstName: schema.string(),
|
||||
lastName: schema.string(),
|
||||
|
@ -56,8 +56,10 @@ const fooMigrationDef: ObjectMigrationDefinition = {
|
|||
2: fooDefV2,
|
||||
};
|
||||
|
||||
const setup = (browserVersion: Version): ObjectTransforms => {
|
||||
const transformsFactory = initTransform(browserVersion);
|
||||
const setup = <UpIn = unknown, UpOut = unknown, DownIn = unknown, DownOut = unknown>(
|
||||
browserVersion: Version
|
||||
): ObjectTransforms<UpIn, UpOut, DownIn, DownOut> => {
|
||||
const transformsFactory = initTransform<UpIn, UpOut, DownIn, DownOut>(browserVersion);
|
||||
return transformsFactory(fooMigrationDef);
|
||||
};
|
||||
|
||||
|
@ -127,7 +129,12 @@ describe('object transform', () => {
|
|||
|
||||
describe('down()', () => {
|
||||
test('it should down transform to a previous version', () => {
|
||||
const fooTransforms = setup(1);
|
||||
const fooTransforms = setup<
|
||||
void,
|
||||
void,
|
||||
{ firstName: string; lastName: string },
|
||||
{ fullName: string }
|
||||
>(1);
|
||||
const { value } = fooTransforms.down({ firstName: 'John', lastName: 'Snow' });
|
||||
const expected = { fullName: 'John Snow' };
|
||||
expect(value).toEqual(expected);
|
||||
|
|
|
@ -45,15 +45,15 @@ const getVersionsMeta = (migrationDefinition: ObjectMigrationDefinition) => {
|
|||
* @param migrationDefinition The object migration definition
|
||||
* @returns An array of transform functions
|
||||
*/
|
||||
const getTransformFns = (
|
||||
const getTransformFns = <I = unknown, O = unknown>(
|
||||
from: Version,
|
||||
to: Version,
|
||||
migrationDefinition: ObjectMigrationDefinition
|
||||
): ObjectTransform[] => {
|
||||
const fns: ObjectTransform[] = [];
|
||||
): Array<ObjectTransform<I, O>> => {
|
||||
const fns: Array<ObjectTransform<I, O>> = [];
|
||||
|
||||
let i = from;
|
||||
let fn: ObjectTransform | undefined;
|
||||
let fn: ObjectTransform<I, O> | undefined;
|
||||
if (to > from) {
|
||||
while (i <= to) {
|
||||
fn = migrationDefinition[i].up;
|
||||
|
@ -96,8 +96,10 @@ const getTransformFns = (
|
|||
* @returns A handler to pass an object migration definition
|
||||
*/
|
||||
export const initTransform =
|
||||
(requestVersion: Version) =>
|
||||
(migrationDefinition: ObjectMigrationDefinition): ObjectTransforms => {
|
||||
<UpIn = unknown, UpOut = unknown, DownIn = unknown, DownOut = unknown>(requestVersion: Version) =>
|
||||
(
|
||||
migrationDefinition: ObjectMigrationDefinition
|
||||
): ObjectTransforms<UpIn, UpOut, DownIn, DownOut> => {
|
||||
const { latestVersion } = getVersionsMeta(migrationDefinition);
|
||||
|
||||
const getVersion = (v: Version | 'latest'): Version => (v === 'latest' ? latestVersion : v);
|
||||
|
@ -143,9 +145,17 @@ export const initTransform =
|
|||
};
|
||||
}
|
||||
|
||||
const fns = getTransformFns(requestVersion, targetVersion, migrationDefinition);
|
||||
const fns = getTransformFns<UpIn, UpOut>(
|
||||
requestVersion,
|
||||
targetVersion,
|
||||
migrationDefinition
|
||||
);
|
||||
|
||||
const value = fns.reduce((acc, fn) => {
|
||||
const res = fn(acc as unknown as UpIn);
|
||||
return res;
|
||||
}, obj as unknown as UpOut);
|
||||
|
||||
const value = fns.reduce((acc, fn) => fn(acc), obj);
|
||||
return { value, error: null };
|
||||
} catch (e) {
|
||||
return {
|
||||
|
@ -179,10 +189,18 @@ export const initTransform =
|
|||
}
|
||||
}
|
||||
|
||||
const fns = getTransformFns(fromVersion, requestVersion, migrationDefinition);
|
||||
const value = fns.reduce((acc, fn) => fn(acc), obj);
|
||||
const fns = getTransformFns<DownIn, DownOut>(
|
||||
fromVersion,
|
||||
requestVersion,
|
||||
migrationDefinition
|
||||
);
|
||||
|
||||
return { value, error: null };
|
||||
const value = fns.reduce((acc, fn) => {
|
||||
const res = fn(acc as unknown as DownIn);
|
||||
return res;
|
||||
}, obj as unknown as DownOut);
|
||||
|
||||
return { value: value as any, error: null };
|
||||
} catch (e) {
|
||||
return {
|
||||
value: null,
|
||||
|
|
|
@ -9,19 +9,24 @@ import type { Type, ValidationError } from '@kbn/config-schema';
|
|||
|
||||
export type Version = number;
|
||||
|
||||
export type ObjectTransform<I extends object = any, O extends object = any> = (input: I) => O;
|
||||
export type ObjectTransform<I = unknown, O = unknown> = (input: I) => O;
|
||||
|
||||
export interface VersionableObject<I extends object = any, O extends object = any> {
|
||||
export interface VersionableObject<
|
||||
UpIn = unknown,
|
||||
UpOut = unknown,
|
||||
DownIn = unknown,
|
||||
DownOut = unknown
|
||||
> {
|
||||
schema?: Type<any>;
|
||||
down?: ObjectTransform;
|
||||
up?: ObjectTransform;
|
||||
down?: ObjectTransform<DownIn, DownOut>;
|
||||
up?: ObjectTransform<UpIn, UpOut>;
|
||||
}
|
||||
|
||||
export interface ObjectMigrationDefinition {
|
||||
[version: Version]: VersionableObject;
|
||||
[version: Version]: VersionableObject<any, any, any, any>;
|
||||
}
|
||||
|
||||
export type TransformReturn<T = object> =
|
||||
export type TransformReturn<T = unknown> =
|
||||
| {
|
||||
value: T;
|
||||
error: null;
|
||||
|
@ -31,22 +36,27 @@ export type TransformReturn<T = object> =
|
|||
error: ValidationError | Error;
|
||||
};
|
||||
|
||||
export interface ObjectTransforms<Current = any, Previous = any, Next = any> {
|
||||
export interface ObjectTransforms<
|
||||
UpIn = unknown,
|
||||
UpOut = unknown,
|
||||
DownIn = unknown,
|
||||
DownOut = unknown
|
||||
> {
|
||||
up: (
|
||||
obj: Current,
|
||||
obj: UpIn,
|
||||
version?: Version | 'latest',
|
||||
options?: {
|
||||
/** Validate the object _before_ up transform */
|
||||
validate?: boolean;
|
||||
}
|
||||
) => TransformReturn<Next>;
|
||||
) => TransformReturn<UpOut>;
|
||||
down: (
|
||||
obj: Current,
|
||||
obj: DownIn,
|
||||
version?: Version | 'latest',
|
||||
options?: {
|
||||
/** Validate the object _before_ down transform */
|
||||
validate?: boolean;
|
||||
}
|
||||
) => TransformReturn<Previous>;
|
||||
) => TransformReturn<DownOut>;
|
||||
validate: (obj: any, version?: Version) => ValidationError | null;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue