Skip to content

Commit

Permalink
Register embeddable functions server side. Adds reference extraction/…
Browse files Browse the repository at this point in the history
…injection to workpads
  • Loading branch information
Corey Robertson committed Aug 24, 2021
1 parent c7d742c commit ed299bc
Show file tree
Hide file tree
Showing 35 changed files with 538 additions and 205 deletions.
1 change: 1 addition & 0 deletions src/plugins/discover/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
],
"optionalPlugins": ["home", "share", "usageCollection"],
"requiredBundles": ["kibanaUtils", "home", "kibanaReact", "fieldFormats"],
"extraPublicDirs": ["common"],
"owner": {
"name": "Kibana App",
"githubTeam": "kibana-app"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
* Side Public License, v 1.
*/

export const SEARCH_EMBEDDABLE_TYPE = 'search';
export { SEARCH_EMBEDDABLE_TYPE } from '../../../common/index';
2 changes: 1 addition & 1 deletion src/plugins/embeddable/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"githubTeam": "kibana-app-services"
},
"requiredPlugins": ["inspector", "uiActions"],
"extraPublicDirs": ["public/lib/test_samples"],
"extraPublicDirs": ["public/lib/test_samples", "common"],
"requiredBundles": ["savedObjects", "kibanaReact", "kibanaUtils"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export type ExpressionsServiceSetup = Pick<
| 'registerType'
| 'run'
| 'fork'
| 'extract'
| 'inject'
>;

export interface ExpressionExecutionParams {
Expand Down
1 change: 1 addition & 0 deletions src/plugins/visualizations/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
*/

export const VISUALIZE_ENABLE_LABS_SETTING = 'visualize:enableLabs';
export const VISUALIZE_EMBEDDABLE_TYPE = 'visualization';
2 changes: 1 addition & 1 deletion src/plugins/visualizations/public/embeddable/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
* Side Public License, v 1.
*/

export const VISUALIZE_EMBEDDABLE_TYPE = 'visualization';
export { VISUALIZE_EMBEDDABLE_TYPE } from '../../common/constants';
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { ExpressionTypeDefinition } from '../../../../../src/plugins/expressions';
import { EmbeddableInput } from '../../../../../src/plugins/embeddable/public';
import { EmbeddableInput } from '../../../../../src/plugins/embeddable/common/';
import { EmbeddableTypes } from './embeddable_types';

export const EmbeddableExpressionType = 'embeddable';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
* 2.0.
*/

import { MAP_SAVED_OBJECT_TYPE } from '../../../../plugins/maps/public';
import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../src/plugins/visualizations/public';
import { MAP_SAVED_OBJECT_TYPE } from '../../../../plugins/maps/common/constants';
import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../src/plugins/visualizations/common/constants';
import { LENS_EMBEDDABLE_TYPE } from '../../../../plugins/lens/common/constants';
import { SEARCH_EMBEDDABLE_TYPE } from '../../../../../src/plugins/discover/public';
import { SEARCH_EMBEDDABLE_TYPE } from '../../../../../src/plugins/discover/common';

export const EmbeddableTypes: {
lens: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ import { savedMap } from './saved_map';
import { savedSearch } from './saved_search';
import { savedVisualization } from './saved_visualization';

export const functions = [savedLens, savedMap, savedSearch, savedVisualization];
export const functions = [savedLens, savedMap, savedVisualization, savedSearch];
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@

import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { PaletteOutput } from 'src/plugins/charts/common';
import { TimeRange, Filter as DataFilter } from 'src/plugins/data/public';
import { EmbeddableInput } from 'src/plugins/embeddable/public';
import { getQueryFilters } from '../../../public/lib/build_embeddable_filters';
import { Filter as DataFilter } from '@kbn/es-query';
import { TimeRange } from 'src/plugins/data/common';
import { EmbeddableInput } from 'src/plugins/embeddable/common';
import { getQueryFilters } from '../../../common/lib/build_embeddable_filters';
import { ExpressionValueFilter, TimeRange as TimeRangeArg } from '../../../types';
import {
EmbeddableTypes,
Expand All @@ -18,7 +19,6 @@ import {
} from '../../expression_types';
import { getFunctionHelp } from '../../../i18n';
import { SavedObjectReference } from '../../../../../../src/core/types';

interface Arguments {
id: string;
title: string | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
*/

import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { getQueryFilters } from '../../../public/lib/build_embeddable_filters';
import { getQueryFilters } from '../../../common/lib/build_embeddable_filters';
import { ExpressionValueFilter, MapCenter, TimeRange as TimeRangeArg } from '../../../types';
import {
EmbeddableTypes,
EmbeddableExpressionType,
EmbeddableExpression,
} from '../../expression_types';
import { getFunctionHelp } from '../../../i18n';
import { MapEmbeddableInput } from '../../../../../plugins/maps/public/embeddable';
import { MapEmbeddableInput } from '../../../../../plugins/maps/public';
import { SavedObjectReference } from '../../../../../../src/core/types';

interface Arguments {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
EmbeddableExpression,
} from '../../expression_types';

import { buildEmbeddableFilters } from '../../../public/lib/build_embeddable_filters';
import { buildEmbeddableFilters } from '../../../common/lib/build_embeddable_filters';
import { ExpressionValueFilter } from '../../../types';
import { getFunctionHelp } from '../../../i18n';
import { SavedObjectReference } from '../../../../../../src/core/types';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
EmbeddableExpressionType,
EmbeddableExpression,
} from '../../expression_types';
import { getQueryFilters } from '../../../public/lib/build_embeddable_filters';
import { getQueryFilters } from '../../../common/lib/build_embeddable_filters';
import { ExpressionValueFilter, TimeRange as TimeRangeArg, SeriesStyle } from '../../../types';
import { getFunctionHelp } from '../../../i18n';
import { SavedObjectReference } from '../../../../../../src/core/types';
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/canvas/canvas_plugin_src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Start as InspectorStart } from '../../../../src/plugins/inspector/publi
import { functions } from './functions/browser';
import { typeFunctions } from './expression_types';
import { renderFunctions, renderFunctionFactories } from './renderers';

interface SetupDeps {
canvas: CanvasSetup;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { buildQueryFilter, Filter } from '@kbn/es-query';
import { ExpressionValueFilter } from '../../types';
// @ts-expect-error untyped local
import { buildBoolArray } from './build_bool_array';
import { TimeRange } from '../../../../../src/plugins/data/public';
import { TimeRange } from '../../../../../src/plugins/data/common';

export interface EmbeddableFilterInput {
filters: Filter[];
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion x-pack/plugins/canvas/public/functions/timelion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { TimeRange } from 'src/plugins/data/common';
import { ExpressionFunctionDefinition, DatatableRow } from 'src/plugins/expressions/public';
import { fetch } from '../../common/lib/fetch';
// @ts-expect-error untyped local
import { buildBoolArray } from '../../public/lib/build_bool_array';
import { buildBoolArray } from '../../common/lib/build_bool_array';
import { Datatable, ExpressionValueFilter } from '../../types';
import { getFunctionHelp } from '../../i18n';
import { InitializeArguments } from './';
Expand Down
8 changes: 8 additions & 0 deletions x-pack/plugins/canvas/server/mocks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export { workpadRouteContextMock, MockWorkpadRouteContext } from './workpad_route_context';
28 changes: 28 additions & 0 deletions x-pack/plugins/canvas/server/mocks/workpad_route_context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { CanvasRouteHandlerContext } from '../workpad_route_context';

export interface MockWorkpadRouteContext extends CanvasRouteHandlerContext {
canvas: {
workpad: {
create: jest.Mock;
get: jest.Mock;
update: jest.Mock;
};
};
}

export const workpadRouteContextMock = {
create: (): MockWorkpadRouteContext['canvas'] => ({
workpad: {
create: jest.fn(),
get: jest.fn(),
update: jest.fn(),
},
}),
};
15 changes: 12 additions & 3 deletions x-pack/plugins/canvas/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { customElementType, workpadType, workpadTemplateType } from './saved_obj
import { initializeTemplates } from './templates';
import { essqlSearchStrategyProvider } from './lib/essql_strategy';
import { getUISettings } from './ui_settings';
import { CanvasRouteHandlerContext, createWorkpadRouteContext } from './workpad_route_context';

interface PluginsSetup {
expressions: ExpressionsServerSetup;
Expand All @@ -48,18 +49,26 @@ export class CanvasPlugin implements Plugin {
}

public setup(coreSetup: CoreSetup<PluginsStart>, plugins: PluginsSetup) {
const expressionsFork = plugins.expressions.fork();

coreSetup.uiSettings.register(getUISettings());
coreSetup.savedObjects.registerType(customElementType);
coreSetup.savedObjects.registerType(workpadType);
coreSetup.savedObjects.registerType(workpadTemplateType);

plugins.features.registerKibanaFeature(getCanvasFeature(plugins));

const canvasRouter = coreSetup.http.createRouter();
const contextProvider = createWorkpadRouteContext({ expressions: expressionsFork });
coreSetup.http.registerRouteHandlerContext<CanvasRouteHandlerContext, 'canvas'>(
'canvas',
contextProvider
);

const canvasRouter = coreSetup.http.createRouter<CanvasRouteHandlerContext>();

initRoutes({
router: canvasRouter,
expressions: plugins.expressions,
expressions: expressionsFork,
bfetch: plugins.bfetch,
logger: this.logger,
});
Expand All @@ -73,7 +82,7 @@ export class CanvasPlugin implements Plugin {
const globalConfig = this.initializerContext.config.legacy.get();
registerCanvasUsageCollector(plugins.usageCollection, globalConfig.kibana.index);

setupInterpreter(plugins.expressions);
setupInterpreter(expressionsFork);

coreSetup.getStartServices().then(([_, depsStart]) => {
const strategy = essqlSearchStrategyProvider();
Expand Down
8 changes: 4 additions & 4 deletions x-pack/plugins/canvas/server/routes/catch_error_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
* 2.0.
*/

import { RequestHandler } from 'src/core/server';
import { RequestHandler, RequestHandlerContext } from 'src/core/server';

export const catchErrorHandler: <P, Q, B>(
fn: RequestHandler<P, Q, B>
) => RequestHandler<P, Q, B> = (fn) => {
export const catchErrorHandler: <P, Q, B, Context extends RequestHandlerContext>(
fn: RequestHandler<P, Q, B, Context>
) => RequestHandler<P, Q, B, Context> = (fn) => {
return async (context, request, response) => {
try {
return await fn(context, request, response);
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/canvas/server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import { initShareablesRoutes } from './shareables';
import { initWorkpadRoutes } from './workpad';
import { initTemplateRoutes } from './templates';
import { initFunctionsRoutes } from './functions';
import { CanvasRouteHandlerContext } from '../workpad_route_context';

export interface RouteInitializerDeps {
router: IRouter;
router: IRouter<CanvasRouteHandlerContext>;
logger: Logger;
expressions: ExpressionsServerSetup;
bfetch: BfetchServerSetup;
Expand Down
62 changes: 22 additions & 40 deletions x-pack/plugins/canvas/server/routes/workpad/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
* 2.0.
*/

import sinon from 'sinon';
import { savedObjectsClientMock, httpServerMock } from 'src/core/server/mocks';
import { CANVAS_TYPE } from '../../../common/lib/constants';
import { workpadRouteContextMock, MockWorkpadRouteContext } from '../../mocks';
import { initializeCreateWorkpadRoute } from './create';
import { kibanaResponseFactory, RequestHandlerContext, RequestHandler } from 'src/core/server';
import { kibanaResponseFactory, RequestHandler } from 'src/core/server';
import { getMockedRouterDeps } from '../test_helpers';

let mockRouteContext = ({
Expand All @@ -18,17 +17,13 @@ let mockRouteContext = ({
client: savedObjectsClientMock.create(),
},
},
} as unknown) as RequestHandlerContext;

const mockedUUID = '123abc';
const now = new Date();
const nowIso = now.toISOString();
canvas: workpadRouteContextMock.create(),
} as unknown) as MockWorkpadRouteContext;

jest.mock('uuid/v4', () => jest.fn().mockReturnValue('123abc'));

describe('POST workpad', () => {
let routeHandler: RequestHandler<any, any, any>;
let clock: sinon.SinonFakeTimers;

beforeEach(() => {
mockRouteContext = ({
Expand All @@ -37,21 +32,21 @@ describe('POST workpad', () => {
client: savedObjectsClientMock.create(),
},
},
} as unknown) as RequestHandlerContext;

clock = sinon.useFakeTimers(now);
canvas: workpadRouteContextMock.create(),
} as unknown) as MockWorkpadRouteContext;

const routerDeps = getMockedRouterDeps();
initializeCreateWorkpadRoute(routerDeps);

routeHandler = routerDeps.router.post.mock.calls[0][1];
});

afterEach(() => {
clock.restore();
});

it(`returns 200 when the workpad is created`, async () => {
const id = 'my-id';
mockRouteContext.canvas.workpad.create.mockResolvedValue({
id,
});

const mockWorkpad = {
pages: [],
};
Expand All @@ -65,18 +60,8 @@ describe('POST workpad', () => {
const response = await routeHandler(mockRouteContext, request, kibanaResponseFactory);

expect(response.status).toBe(200);
expect(response.payload).toEqual({ ok: true, id: `workpad-${mockedUUID}` });
expect(mockRouteContext.core.savedObjects.client.create).toBeCalledWith(
CANVAS_TYPE,
{
...mockWorkpad,
'@timestamp': nowIso,
'@created': nowIso,
},
{
id: `workpad-${mockedUUID}`,
}
);
expect(response.payload).toEqual({ ok: true, id });
expect(mockRouteContext.canvas.workpad.create).toBeCalledWith(mockWorkpad);
});

it(`returns bad request if create is unsuccessful`, async () => {
Expand All @@ -86,7 +71,7 @@ describe('POST workpad', () => {
body: {},
});

(mockRouteContext.core.savedObjects.client.create as jest.Mock).mockImplementation(() => {
mockRouteContext.canvas.workpad.create.mockImplementation(() => {
throw mockRouteContext.core.savedObjects.client.errors.createBadRequestError('bad request');
});

Expand All @@ -109,6 +94,11 @@ describe('POST workpad', () => {
},
};

const id = 'my-id';
mockRouteContext.canvas.workpad.create.mockResolvedValue({
id,
});

(mockRouteContext.core.savedObjects.client.get as jest.Mock).mockResolvedValue(
mockTemplateResponse
);
Expand All @@ -122,17 +112,9 @@ describe('POST workpad', () => {
const response = await routeHandler(mockRouteContext, request, kibanaResponseFactory);

expect(response.status).toBe(200);
expect(response.payload).toEqual({ ok: true, id: `workpad-${mockedUUID}` });
expect(mockRouteContext.core.savedObjects.client.create).toBeCalledWith(
CANVAS_TYPE,
{
...mockTemplateResponse.attributes.template,
'@timestamp': nowIso,
'@created': nowIso,
},
{
id: `workpad-${mockedUUID}`,
}
expect(response.payload).toEqual({ ok: true, id });
expect(mockRouteContext.canvas.workpad.create).toBeCalledWith(
mockTemplateResponse.attributes.template
);
});
});
Loading

0 comments on commit ed299bc

Please sign in to comment.