Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up data plugin #39554

Closed
wants to merge 9 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ import { fromExpression, Ast } from '@kbn/interpreter/common';

import {
ExpressionsService,
RenderFunctionsRegistry,
RenderFunction,
Interpreter,
ExpressionsServiceDependencies,
Result,
ExpressionsSetup,
RenderFunctionsRegistry,
} from './expressions_service';
import { mount } from 'enzyme';
import React from 'react';
Expand All @@ -45,28 +44,29 @@ describe('expressions_service', () => {
let interpretAstMock: jest.Mocked<Interpreter>['interpretAst'];
let interpreterMock: jest.Mocked<Interpreter>;
let renderFunctionMock: jest.Mocked<RenderFunction>;
let setupPluginsMock: ExpressionsServiceDependencies;
const expressionResult: Result = { type: 'render', as: RENDERER_ID, value: {} };

let api: ExpressionsSetup;
let testExpression: string;
let testAst: Ast;

beforeEach(() => {
interpretAstMock = jest.fn(_ => Promise.resolve(expressionResult));
interpretAstMock = jest.fn((ast, context, handlers) => Promise.resolve(expressionResult));
interpreterMock = { interpretAst: interpretAstMock };
renderFunctionMock = ({
render: jest.fn(),
} as unknown) as jest.Mocked<RenderFunction>;
setupPluginsMock = {
interpreter: {
getInterpreter: () => Promise.resolve({ interpreter: interpreterMock }),
renderersRegistry: ({
get: (id: string) => (id === RENDERER_ID ? renderFunctionMock : null),
} as unknown) as RenderFunctionsRegistry,
},
};
api = new ExpressionsService().setup(setupPluginsMock);

jest.doMock('plugins/interpreter/interpreter', () => ({
getInterpreter: () => Promise.resolve({ interpreter: interpreterMock }),
}));
jest.doMock('plugins/interpreter/registries', () => ({
renderersRegistry: ({
get: (id: string) => (id === RENDERER_ID ? renderFunctionMock : null),
} as unknown) as RenderFunctionsRegistry,
}));

api = new ExpressionsService().setup();
testExpression = 'test | expression';
testAst = fromExpression(testExpression);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@

import { Ast } from '@kbn/interpreter/common';

// TODO:
// this type import and the types below them should be switched to the types of
// the interpreter plugin itself once they are ready
// TODO: These imports should be switched to the types of
// the interpreter plugin itself once they are ready.
import { Registry } from '@kbn/interpreter/common';
import { Adapters } from 'ui/inspector';
import { TimeRange } from 'ui/timefilter/time_history';
Expand Down Expand Up @@ -71,23 +70,23 @@ export interface Interpreter {
interpretAst(ast: Ast, context: Context, handlers: Handlers): Promise<Result>;
}

type InterpreterGetter = () => Promise<{ interpreter: Interpreter }>;

export interface ExpressionsServiceDependencies {
interpreter: {
renderersRegistry: RenderFunctionsRegistry;
getInterpreter: InterpreterGetter;
};
interface InterpreterGetter {
getInterpreter: () => Promise<{ interpreter: Interpreter }>;
}

/**
* Expressions Service
* @internal
*/
export class ExpressionsService {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit unrelated but shouldn't we have registerFunction here?
I saw @ppisljar added it to expressions on markdown vis.

public setup({
interpreter: { renderersRegistry, getInterpreter },
}: ExpressionsServiceDependencies) {
public setup() {
// TODO: this is temporarily imported here to avoid circular imports, until interpreter
// moves into the expressions service.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { getInterpreter }: InterpreterGetter = require('plugins/interpreter/interpreter');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { renderersRegistry } = require('plugins/interpreter/registries');

const run = createRunFn(
renderersRegistry,
getInterpreter().then(({ interpreter }) => interpreter)
Expand Down Expand Up @@ -120,9 +119,9 @@ export class ExpressionsService {
};
}

public stop() {
// nothing to do here yet
}
public start() {}

public stop() {}
}

/** @public */
Expand Down
93 changes: 27 additions & 66 deletions src/legacy/core_plugins/data/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,77 +17,38 @@
* under the License.
*/

// TODO these are imports from the old plugin world.
// Once the new platform is ready, they can get removed
// and handled by the platform itself in the setup method
// of the ExpressionExectorService
// @ts-ignore
import { renderersRegistry } from 'plugins/interpreter/registries';
import { ExpressionsService, ExpressionsSetup } from './expressions';
import { SearchService, SearchSetup } from './search';
import { QueryService, QuerySetup } from './query';
import { FilterService, FilterSetup } from './filter';
import { IndexPatternsService, IndexPatternsSetup } from './index_patterns';

export class DataPlugin {
// Exposed services, sorted alphabetically
private readonly expressions: ExpressionsService;
private readonly filter: FilterService;
private readonly indexPatterns: IndexPatternsService;
private readonly search: SearchService;
private readonly query: QueryService;

constructor() {
this.indexPatterns = new IndexPatternsService();
this.filter = new FilterService();
this.query = new QueryService();
this.search = new SearchService();
this.expressions = new ExpressionsService();
}

public setup(): DataSetup {
// TODO: this is imported here to avoid circular imports.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { getInterpreter } = require('plugins/interpreter/interpreter');
const indexPatternsService = this.indexPatterns.setup();
return {
expressions: this.expressions.setup({
interpreter: {
getInterpreter,
renderersRegistry,
},
}),
indexPatterns: indexPatternsService,
filter: this.filter.setup({
indexPatterns: indexPatternsService.indexPatterns,
}),
search: this.search.setup(),
query: this.query.setup(),
};
}
/**
* Data Plugin - public
*
* This is the entry point for the entire client-side public contract of the plugin.
* If something is not explicitly exported here, you can safely assume it is private
* to the plugin and not considered stable.
*
* All stateful contracts will be injected by the platform at runtime, and are defined
* in the setup/start interfaces. The remaining items exported here are either types,
* or static code.
*/
import { PluginInitializer, PluginInitializerContext } from '../../../../core/public';
import {
DataPublicPlugin,
DataSetup,
DataSetupPlugins,
DataStart,
DataStartPlugins,
} from './plugin';

public stop() {
this.expressions.stop();
this.indexPatterns.stop();
this.filter.stop();
this.search.stop();
this.query.stop();
}
}
// This is what Core looks for when loading our plugin
export const plugin: PluginInitializer<DataSetup, DataStart, DataSetupPlugins, DataStartPlugins> = (
initializerContext: PluginInitializerContext
) => {
return new DataPublicPlugin();
};

/** @public */
export interface DataSetup {
expressions: ExpressionsSetup;
indexPatterns: IndexPatternsSetup;
filter: FilterSetup;
search: SearchSetup;
query: QuerySetup;
}
/** @public interfaces for stateful services */
export { DataSetup };

/** @public types */
export { ExpressionRenderer, ExpressionRendererProps, ExpressionRunner } from './expressions';

/** @public types */
export { IndexPattern, StaticIndexPattern, StaticIndexPatternField, Field } from './index_patterns';
export { Query } from './query';
export { FilterManager, FilterStateManager, uniqFilters } from './filter/filter_manager';
Expand Down
105 changes: 105 additions & 0 deletions src/legacy/core_plugins/data/public/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { CoreSetup, CoreStart, Plugin } from '../../../../core/public';

// Services
import { ExpressionsService, ExpressionsSetup } from './expressions';
import { FilterService, FilterSetup } from './filter';
import { IndexPatternsService, IndexPatternsSetup } from './index_patterns';
import { QueryService, QuerySetup } from './query';
import { SearchService, SearchSetup } from './search';

/**
* Data Plugin - public
*
* Shared services for applications to access, query, and manipulate data in Kibana.
*/
export class DataPublicPlugin
implements Plugin<DataSetup, DataStart, DataSetupPlugins, DataStartPlugins> {
// Exposed services, sorted alphabetically
private readonly expressions = new ExpressionsService();
private readonly filter = new FilterService();
private readonly indexPatterns = new IndexPatternsService();
private readonly query = new QueryService();
private readonly search = new SearchService();

public setup(core: CoreSetup, plugins: DataSetupPlugins): DataSetup {
const indexPatternsSetup = this.indexPatterns.setup();

return {
expressions: this.expressions.setup(),
indexPatterns: indexPatternsSetup,
filter: this.filter.setup({
indexPatterns: indexPatternsSetup.indexPatterns,
}),
query: this.query.setup(),
search: this.search.setup(),
};
}

public start(core: CoreStart, plugins: DataStartPlugins): DataStart {
return {};
}

public stop() {
this.expressions.stop();
this.indexPatterns.stop();
this.filter.stop();
this.query.stop();
this.search.stop();
}
}

/**
* Interface for this plugin's returned `setup` contract.
*
* @public
*/
export interface DataSetup {
expressions: ExpressionsSetup;
indexPatterns: IndexPatternsSetup;
filter: FilterSetup;
query: QuerySetup;
search: SearchSetup;
}

/**
* Interface for this plugin's returned `start` contract.
*
* @public
*/
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DataStart {}

/**
* Interface for any dependencies on other plugins' `setup` contracts.
*
* @internal
*/
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DataSetupPlugins {}

/**
* Interface for any dependencies on other plugins' `start` contracts.
*
* @internal
*/
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DataStartPlugins {}
1 change: 1 addition & 0 deletions src/legacy/core_plugins/data/public/query/query_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,5 @@ export class QueryService {
/** @public */
export type QuerySetup = ReturnType<QueryService['setup']>;

/** @public types */
export { Query } from './query_bar';
32 changes: 26 additions & 6 deletions src/legacy/core_plugins/data/public/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,31 @@
* under the License.
*/

import { DataPlugin } from './index';

/**
* We export data here so that users importing from 'plugins/data'
* will automatically receive the response value of the `setup` contract, mimicking
* the data that will eventually be injected by the new platform.
* New Platform Shim
*
* In this file, we import any legacy dependencies we have, and shim them into
* our plugin by manually constructing the values that the new platform will
* eventually be passing to the `setup` method of our plugin definition.
*
* The idea is that our `plugin.ts` can stay "pure" and not contain any legacy
* world code. Then when it comes time to migrate to the new platform, we can
* simply delete this shim file.
*
* We are also calling `setup` here and exporting our public contract so that
* other legacy plugins are able to import from '../core_plugins/data/setup'
* and receive the response value of the `setup` contract, mimicking the
* data that will eventually be injected by the new platform.
*/
export const data = new DataPlugin().setup();
import { npSetup } from 'ui/new_platform';

import { CoreSetup } from '../../../../core/public';
import { DataPublicPlugin, DataSetupPlugins } from './plugin';

// core shims
const coreSetup: CoreSetup = npSetup.core;

// plugin dependency shims
const pluginsSetup: DataSetupPlugins = {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great. :)


export const data = new DataPublicPlugin().setup(coreSetup, pluginsSetup);