Skip to content

Commit

Permalink
👌 Refactor based on feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
dej611 committed Sep 8, 2023
1 parent 7870b82 commit d9b0427
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 17 deletions.
2 changes: 0 additions & 2 deletions packages/kbn-content-management-utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,6 @@ export interface SavedObjectSearchOptions {

/** Saved Object update options - Pick and Omit to customize */
export interface SavedObjectUpdateOptions<Attributes = unknown> {
/** Overwrite existing documents (defaults to false) */
overwrite?: boolean;
/** Array of referenced saved objects. */
references?: Reference[];
version?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export type GenericVisualizationCrudTypes<
ContentType,
Attr,
Pick<SavedObjectCreateOptions, 'overwrite' | 'references'>,
Pick<SavedObjectUpdateOptions, 'overwrite' | 'references'>,
Pick<SavedObjectUpdateOptions, 'references'>,
object
>;

Expand Down
19 changes: 12 additions & 7 deletions x-pack/plugins/lens/common/content_management/v1/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import type { UpdateIn } from '@kbn/content-management-plugin/common';
import type { ContentManagementCrudTypes } from '@kbn/content-management-utils';

import type { LensContentType } from '../types';
Expand Down Expand Up @@ -39,13 +40,17 @@ export type LensSavedObjectAttributes = {
state?: unknown;
};

export type LensCrudTypes = ContentManagementCrudTypes<
LensContentType,
LensSavedObjectAttributes,
CreateOptions,
UpdateOptions,
LensSearchQuery
>;
// Need to handle update in Lens in a bit different way
export type LensCrudTypes = Omit<
ContentManagementCrudTypes<
LensContentType,
LensSavedObjectAttributes,
CreateOptions,
UpdateOptions,
LensSearchQuery
>,
'UpdateIn'
> & { UpdateIn: UpdateIn<LensContentType, LensSavedObjectAttributes, UpdateOptions> };

export type LensSavedObject = LensCrudTypes['Item'];
export type PartialLensSavedObject = LensCrudTypes['PartialItem'];
Expand Down
114 changes: 113 additions & 1 deletion x-pack/plugins/lens/server/content_management/lens_storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,19 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import Boom from '@hapi/boom';
import type { SavedObjectsFindOptions } from '@kbn/core-saved-objects-api-server';
import type { StorageContext } from '@kbn/content-management-plugin/server';
import { SOContentStorage, tagsToFindOptions } from '@kbn/content-management-utils';
import type { SavedObject, SavedObjectReference } from '@kbn/core-saved-objects-api-server';

import { CONTENT_ID, LensCrudTypes } from '../../common/content_management';
import {
CONTENT_ID,
type LensCrudTypes,
type LensSavedObject,
type LensSavedObjectAttributes,
type PartialLensSavedObject,
} from '../../common/content_management';
import { cmServicesDefinition } from '../../common/content_management/cm_services';

const searchArgsToSOFindOptions = (args: LensCrudTypes['SearchIn']): SavedObjectsFindOptions => {
Expand All @@ -26,6 +35,52 @@ const searchArgsToSOFindOptions = (args: LensCrudTypes['SearchIn']): SavedObject
};
};

const savedObjectClientFromRequest = async (ctx: StorageContext) => {
if (!ctx.requestHandlerContext) {
throw new Error('Storage context.requestHandlerContext missing.');
}

const { savedObjects } = await ctx.requestHandlerContext.core;
return savedObjects.client;
};

type PartialSavedObject<T> = Omit<SavedObject<Partial<T>>, 'references'> & {
references: SavedObjectReference[] | undefined;
};

function savedObjectToLensSavedObject(
savedObject:
| SavedObject<LensSavedObjectAttributes>
| PartialSavedObject<LensSavedObjectAttributes>
): LensSavedObject | PartialLensSavedObject {
const {
id,
type,
updated_at: updatedAt,
created_at: createdAt,
attributes: { title, description, state, visualizationType },
references,
error,
namespaces,
} = savedObject;

return {
id,
type,
updatedAt,
createdAt,
attributes: {
title,
description,
visualizationType,
state,
},
references,
error,
namespaces,
};
}

export class LensStorage extends SOContentStorage<LensCrudTypes> {
constructor() {
super({
Expand All @@ -36,4 +91,61 @@ export class LensStorage extends SOContentStorage<LensCrudTypes> {
allowedSavedObjectAttributes: ['title', 'description', 'visualizationType', 'state'],
});
}

/**
* Lens requires a custom update function because of https://github.com/elastic/kibana/issues/160116
* where a forced create with overwrite flag is used instead of regular update
*/
async update(
ctx: StorageContext,
id: string,
data: LensCrudTypes['UpdateIn']['data'],
options: LensCrudTypes['UpdateOptions']
): Promise<LensCrudTypes['UpdateOut']> {
const {
utils: { getTransforms },
version: { request: requestVersion },
} = ctx;
const transforms = getTransforms(cmServicesDefinition, requestVersion);

// Validate input (data & options) & UP transform them to the latest version
const { value: dataToLatest, error: dataError } = transforms.update.in.data.up<
LensSavedObjectAttributes,
LensSavedObjectAttributes
>(data);
if (dataError) {
throw Boom.badRequest(`Invalid data. ${dataError.message}`);
}

const { value: optionsToLatest, error: optionsError } = transforms.update.in.options.up<
LensCrudTypes['CreateOptions'],
LensCrudTypes['CreateOptions']
>(options);
if (optionsError) {
throw Boom.badRequest(`Invalid options. ${optionsError.message}`);
}

// Save data in DB
const soClient = await savedObjectClientFromRequest(ctx);

const savedObject = await soClient.create<LensSavedObjectAttributes>(CONTENT_ID, dataToLatest, {
id,
overwrite: true,
...optionsToLatest,
});

// Validate DB response and DOWN transform to the request version
const { value, error: resultError } = transforms.update.out.result.down<
LensCrudTypes['UpdateOut'],
LensCrudTypes['UpdateOut']
>({
item: savedObjectToLensSavedObject(savedObject),
});

if (resultError) {
throw Boom.badRequest(`Invalid response. ${resultError.message}`);
}

return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@ const createOptionsSchema = schema.object({
references: schema.maybe(createOptionsSchemas.references),
});

const updateOptionsSchema = schema.object({
overwrite: schema.maybe(createOptionsSchemas.overwrite),
references: schema.maybe(createOptionsSchemas.references),
});

// Content management service definition.
// We need it for BWC support between different versions of the content
export const serviceDefinition: ServicesDefinition = {
Expand Down Expand Up @@ -72,7 +67,7 @@ export const serviceDefinition: ServicesDefinition = {
update: {
in: {
options: {
schema: updateOptionsSchema,
schema: createOptionsSchema, // same as create
},
data: {
schema: mapAttributesSchema,
Expand Down

0 comments on commit d9b0427

Please sign in to comment.