mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
* Initial commit - cleanup * cleanup * tsing * ts fixes * Fix jest test * Code review fxes * Remove empty file reference Remove empty file reference * code review Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
71bda5f289
commit
71401c62df
26 changed files with 140 additions and 521 deletions
|
@ -18,11 +18,7 @@
|
|||
*/
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import {
|
||||
ISearchContext,
|
||||
SYNC_SEARCH_STRATEGY,
|
||||
ISearchGeneric,
|
||||
} from '../../../src/plugins/data/public';
|
||||
import { ISearchContext, SYNC_SEARCH_STRATEGY } from '../../../src/plugins/data/public';
|
||||
import { TSearchStrategyProvider, ISearchStrategy } from '../../../src/plugins/data/public';
|
||||
|
||||
import { DEMO_SEARCH_STRATEGY, IDemoResponse } from '../common';
|
||||
|
@ -54,15 +50,15 @@ import { DEMO_SEARCH_STRATEGY, IDemoResponse } from '../common';
|
|||
* @param search - a search function to access other strategies that have already been registered.
|
||||
*/
|
||||
export const demoClientSearchStrategyProvider: TSearchStrategyProvider<typeof DEMO_SEARCH_STRATEGY> = (
|
||||
context: ISearchContext,
|
||||
search: ISearchGeneric
|
||||
context: ISearchContext
|
||||
): ISearchStrategy<typeof DEMO_SEARCH_STRATEGY> => {
|
||||
const syncStrategyProvider = context.getSearchStrategy(SYNC_SEARCH_STRATEGY);
|
||||
const { search } = syncStrategyProvider(context);
|
||||
return {
|
||||
search: (request, options) =>
|
||||
search(
|
||||
{ ...request, serverStrategy: DEMO_SEARCH_STRATEGY },
|
||||
options,
|
||||
SYNC_SEARCH_STRATEGY
|
||||
) as Observable<IDemoResponse>,
|
||||
search: (request, options) => {
|
||||
return search({ ...request, serverStrategy: DEMO_SEARCH_STRATEGY }, options) as Observable<
|
||||
IDemoResponse
|
||||
>;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -17,12 +17,10 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { PluginInitializer, PluginInitializerContext } from 'kibana/public';
|
||||
import { PluginInitializer } from 'kibana/public';
|
||||
|
||||
import { DemoDataPlugin } from './plugin';
|
||||
|
||||
export { DEMO_SEARCH_STRATEGY } from '../common';
|
||||
|
||||
export const plugin: PluginInitializer<void, void> = (
|
||||
initializerContext: PluginInitializerContext
|
||||
) => new DemoDataPlugin(initializerContext);
|
||||
export const plugin: PluginInitializer<void, void> = () => new DemoDataPlugin();
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import { DataPublicPluginSetup } from '../../../src/plugins/data/public';
|
||||
import { Plugin, CoreSetup, PluginInitializerContext } from '../../../src/core/public';
|
||||
import { Plugin, CoreSetup } from '../../../src/core/public';
|
||||
import { DEMO_SEARCH_STRATEGY } from '../common';
|
||||
import { demoClientSearchStrategyProvider } from './demo_search_strategy';
|
||||
import { IDemoRequest, IDemoResponse } from '../common';
|
||||
|
@ -47,10 +47,8 @@ declare module '../../../src/plugins/data/public' {
|
|||
}
|
||||
|
||||
export class DemoDataPlugin implements Plugin {
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
public setup(core: CoreSetup, deps: DemoDataSearchSetupDependencies) {
|
||||
deps.data.search.registerSearchStrategyProvider(
|
||||
this.initializerContext.opaqueId,
|
||||
DEMO_SEARCH_STRATEGY,
|
||||
demoClientSearchStrategyProvider
|
||||
);
|
||||
|
|
|
@ -28,12 +28,13 @@ import {
|
|||
EuiSideNav,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { AppMountContext, AppMountParameters } from '../../../src/core/public';
|
||||
import { AppMountParameters, CoreStart } from '../../../src/core/public';
|
||||
import { EsSearchTest } from './es_strategy';
|
||||
import { Page } from './page';
|
||||
import { DemoStrategy } from './demo_strategy';
|
||||
import { DocumentationPage } from './documentation';
|
||||
import { SearchApiPage } from './search_api';
|
||||
import { AppPluginStartDependencies, SearchBarComponentParams } from './types';
|
||||
|
||||
const Home = () => <DocumentationPage />;
|
||||
|
||||
|
@ -44,7 +45,7 @@ interface PageDef {
|
|||
}
|
||||
|
||||
type NavProps = RouteComponentProps & {
|
||||
navigateToApp: AppMountContext['core']['application']['navigateToApp'];
|
||||
navigateToApp: CoreStart['application']['navigateToApp'];
|
||||
pages: PageDef[];
|
||||
};
|
||||
|
||||
|
@ -71,7 +72,7 @@ const Nav = withRouter(({ history, navigateToApp, pages }: NavProps) => {
|
|||
|
||||
const buildPage = (page: PageDef) => <Page title={page.title}>{page.component}</Page>;
|
||||
|
||||
const SearchApp = ({ basename, context }: { basename: string; context: AppMountContext }) => {
|
||||
const SearchApp = ({ basename, data, application }: SearchBarComponentParams) => {
|
||||
const pages: PageDef[] = [
|
||||
{
|
||||
id: 'home',
|
||||
|
@ -86,12 +87,12 @@ const SearchApp = ({ basename, context }: { basename: string; context: AppMountC
|
|||
{
|
||||
title: 'ES search strategy',
|
||||
id: 'esSearch',
|
||||
component: <EsSearchTest search={context.search!.search} />,
|
||||
component: <EsSearchTest search={data.search.search} />,
|
||||
},
|
||||
{
|
||||
title: 'Demo search strategy',
|
||||
id: 'demoSearch',
|
||||
component: <DemoStrategy search={context.search!.search} />,
|
||||
component: <DemoStrategy search={data.search.search} />,
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -103,7 +104,7 @@ const SearchApp = ({ basename, context }: { basename: string; context: AppMountC
|
|||
<Router basename={basename}>
|
||||
<EuiPage>
|
||||
<EuiPageSideBar>
|
||||
<Nav navigateToApp={context.core.application.navigateToApp} pages={pages} />
|
||||
<Nav navigateToApp={application.navigateToApp} pages={pages} />
|
||||
</EuiPageSideBar>
|
||||
<Route path="/" exact component={Home} />
|
||||
{routes}
|
||||
|
@ -113,10 +114,14 @@ const SearchApp = ({ basename, context }: { basename: string; context: AppMountC
|
|||
};
|
||||
|
||||
export const renderApp = (
|
||||
context: AppMountContext,
|
||||
coreStart: CoreStart,
|
||||
deps: AppPluginStartDependencies,
|
||||
{ appBasePath, element }: AppMountParameters
|
||||
) => {
|
||||
ReactDOM.render(<SearchApp basename={appBasePath} context={context} />, element);
|
||||
ReactDOM.render(
|
||||
<SearchApp basename={appBasePath} data={deps.data} application={coreStart.application} />,
|
||||
element
|
||||
);
|
||||
|
||||
return () => ReactDOM.unmountComponentAtNode(element);
|
||||
};
|
||||
|
|
|
@ -38,8 +38,6 @@ import serverPlugin from '!!raw-loader!./../../../src/plugins/data/server/search
|
|||
// @ts-ignore
|
||||
import serverStrategy from '!!raw-loader!./../../../src/plugins/data/server/search/es_search/es_search_strategy';
|
||||
|
||||
// @ts-ignore
|
||||
import publicPlugin from '!!raw-loader!./../../../src/plugins/data/public/search/es_search/es_search_service';
|
||||
// @ts-ignore
|
||||
import publicStrategy from '!!raw-loader!./../../../src/plugins/data/public/search/es_search/es_search_strategy';
|
||||
|
||||
|
@ -125,10 +123,7 @@ export class EsSearchTest extends React.Component<Props, State> {
|
|||
codeSections={[
|
||||
{
|
||||
title: 'Public',
|
||||
code: [
|
||||
{ description: 'es_search_service.ts', snippet: publicPlugin },
|
||||
{ description: 'es_search_strategy.ts', snippet: publicStrategy },
|
||||
],
|
||||
code: [{ description: 'es_search_strategy.ts', snippet: publicStrategy }],
|
||||
},
|
||||
{
|
||||
title: 'Server',
|
||||
|
|
|
@ -17,22 +17,18 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup } from 'kibana/public';
|
||||
import { ISearchAppMountContext } from '../../../src/plugins/data/public';
|
||||
import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public';
|
||||
import { AppPluginStartDependencies } from './types';
|
||||
|
||||
declare module 'kibana/public' {
|
||||
interface AppMountContext {
|
||||
search?: ISearchAppMountContext;
|
||||
}
|
||||
}
|
||||
export class SearchExplorerPlugin implements Plugin {
|
||||
public setup(core: CoreSetup) {
|
||||
public setup(core: CoreSetup<AppPluginStartDependencies>) {
|
||||
core.application.register({
|
||||
id: 'searchExplorer',
|
||||
title: 'Search Explorer',
|
||||
async mount(context, params) {
|
||||
async mount(params: AppMountParameters) {
|
||||
const [coreStart, depsStart] = await core.getStartServices();
|
||||
const { renderApp } = await import('./application');
|
||||
return renderApp(context, params);
|
||||
return renderApp(coreStart, depsStart, params);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -19,10 +19,6 @@
|
|||
import React from 'react';
|
||||
import { GuideSection } from './guide_section';
|
||||
|
||||
// @ts-ignore
|
||||
import publicSetupContract from '!!raw-loader!./../../../src/plugins/data/public/search/i_search_setup';
|
||||
// @ts-ignore
|
||||
import publicSearchStrategy from '!!raw-loader!./../../../src/plugins/data/public/search/i_search_strategy';
|
||||
// @ts-ignore
|
||||
import publicSearch from '!!raw-loader!./../../../src/plugins/data/public/search/i_search';
|
||||
// @ts-ignore
|
||||
|
@ -31,8 +27,6 @@ import publicPlugin from '!!raw-loader!./../../../src/plugins/data/public/search
|
|||
// @ts-ignore
|
||||
import serverSetupContract from '!!raw-loader!./../../../src/plugins/data/server/search/i_search_setup';
|
||||
// @ts-ignore
|
||||
import serverSearchStrategy from '!!raw-loader!./../../../src/plugins/data/server/search/i_search_strategy';
|
||||
// @ts-ignore
|
||||
import serverSearch from '!!raw-loader!./../../../src/plugins/data/server/search/i_search';
|
||||
// @ts-ignore
|
||||
import serverPlugin from '!!raw-loader!./../../../src/plugins/data/server/search/search_service';
|
||||
|
@ -47,18 +41,10 @@ export const SearchApiPage = () => (
|
|||
description: 'search_service.ts',
|
||||
snippet: publicPlugin,
|
||||
},
|
||||
{
|
||||
description: `i_search_setup.ts`,
|
||||
snippet: publicSetupContract,
|
||||
},
|
||||
{
|
||||
description: 'i_search',
|
||||
snippet: publicSearch,
|
||||
},
|
||||
{
|
||||
description: 'i_search_strategy',
|
||||
snippet: publicSearchStrategy,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -76,10 +62,6 @@ export const SearchApiPage = () => (
|
|||
description: 'i_search',
|
||||
snippet: serverSearch,
|
||||
},
|
||||
{
|
||||
description: 'i_search_strategy',
|
||||
snippet: serverSearchStrategy,
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
|
|
|
@ -17,8 +17,15 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { ISearchGeneric } from './i_search';
|
||||
import { CoreStart } from 'kibana/public';
|
||||
import { DataPublicPluginStart } from '../../../src/plugins/data/public';
|
||||
|
||||
export interface ISearchAppMountContext {
|
||||
search: ISearchGeneric;
|
||||
export interface AppPluginStartDependencies {
|
||||
data: DataPublicPluginStart;
|
||||
}
|
||||
|
||||
export interface SearchBarComponentParams {
|
||||
application: CoreStart['application'];
|
||||
basename: string;
|
||||
data: DataPublicPluginStart;
|
||||
}
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public';
|
||||
import { UiActionsStart, UiActionsSetup } from 'src/plugins/ui_actions/public';
|
||||
import { ISearchAppMountContext } from '../../../src/plugins/data/public';
|
||||
import {
|
||||
PHONE_TRIGGER,
|
||||
USER_TRIGGER,
|
||||
|
@ -38,12 +37,6 @@ import {
|
|||
SHOWCASE_PLUGGABILITY_ACTION,
|
||||
} from './actions/actions';
|
||||
|
||||
declare module 'kibana/public' {
|
||||
interface AppMountContext {
|
||||
search?: ISearchAppMountContext;
|
||||
}
|
||||
}
|
||||
|
||||
interface StartDeps {
|
||||
uiActions: UiActionsStart;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPubli
|
|||
private readonly packageInfo: PackageInfo;
|
||||
|
||||
constructor(initializerContext: PluginInitializerContext) {
|
||||
this.searchService = new SearchService(initializerContext);
|
||||
this.searchService = new SearchService();
|
||||
this.queryService = new QueryService();
|
||||
this.fieldFormatsService = new FieldFormatsService();
|
||||
this.storage = new Storage(window.localStorage);
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* 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 { createAppMountSearchContext } from './create_app_mount_context_search';
|
||||
import { from } from 'rxjs';
|
||||
|
||||
describe('Create app mount search context', () => {
|
||||
it('Returns search fn when there are no strategies', () => {
|
||||
const context = createAppMountSearchContext({});
|
||||
expect(context.search).toBeDefined();
|
||||
});
|
||||
|
||||
it(`Search throws an error when the strategy doesn't exist`, () => {
|
||||
const context = createAppMountSearchContext({});
|
||||
expect(() => context.search({}, {}, 'noexist').toPromise()).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Strategy with name noexist does not exist"`
|
||||
);
|
||||
});
|
||||
|
||||
it(`Search fn is called on appropriate strategy name`, done => {
|
||||
const context = createAppMountSearchContext({
|
||||
mysearch: search =>
|
||||
Promise.resolve({
|
||||
search: () => from(Promise.resolve({ percentComplete: 98 })),
|
||||
}),
|
||||
anothersearch: search =>
|
||||
Promise.resolve({
|
||||
search: () => from(Promise.resolve({ percentComplete: 0 })),
|
||||
}),
|
||||
});
|
||||
|
||||
context.search({}, {}, 'mysearch').subscribe(response => {
|
||||
expect(response).toEqual({ percentComplete: 98 });
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it(`Search fn is called with the passed in request object`, done => {
|
||||
const context = createAppMountSearchContext({
|
||||
mysearch: search => {
|
||||
return Promise.resolve({
|
||||
search: request => {
|
||||
expect(request).toEqual({ greeting: 'hi' });
|
||||
return from(Promise.resolve({}));
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
context.search({ greeting: 'hi' } as any, {}, 'mysearch').subscribe(
|
||||
response => {},
|
||||
() => {},
|
||||
done
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* 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 { mergeMap } from 'rxjs/operators';
|
||||
import { from } from 'rxjs';
|
||||
import { ISearchAppMountContext } from './i_search_app_mount_context';
|
||||
import { ISearchGeneric } from './i_search';
|
||||
import {
|
||||
TSearchStrategiesMap,
|
||||
ISearchStrategy,
|
||||
TSearchStrategyProviderEnhanced,
|
||||
} from './i_search_strategy';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
import { DEFAULT_SEARCH_STRATEGY } from '../../common/search';
|
||||
|
||||
export const createAppMountSearchContext = (
|
||||
searchStrategies: TSearchStrategiesMap
|
||||
): ISearchAppMountContext => {
|
||||
const getSearchStrategy = <K extends TStrategyTypes = typeof DEFAULT_SEARCH_STRATEGY>(
|
||||
strategyName?: K
|
||||
): Promise<ISearchStrategy<K>> => {
|
||||
const strategyProvider = searchStrategies[
|
||||
strategyName ? strategyName : DEFAULT_SEARCH_STRATEGY
|
||||
] as TSearchStrategyProviderEnhanced<K> | undefined;
|
||||
if (!strategyProvider) {
|
||||
throw new Error(`Strategy with name ${strategyName} does not exist`);
|
||||
}
|
||||
return strategyProvider(search);
|
||||
};
|
||||
|
||||
const search: ISearchGeneric = (request, options, strategyName) => {
|
||||
const strategyPromise = getSearchStrategy(strategyName);
|
||||
return from(strategyPromise).pipe(mergeMap(strategy => strategy.search(request, options)));
|
||||
};
|
||||
|
||||
return { search };
|
||||
};
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* 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 { coreMock } from '../../../../../core/public/mocks';
|
||||
import { EsSearchService } from './es_search_service';
|
||||
import { CoreSetup } from '../../../../../core/public';
|
||||
import { searchSetupMock } from '../mocks';
|
||||
|
||||
describe('ES search strategy service', () => {
|
||||
let service: EsSearchService;
|
||||
let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
|
||||
beforeEach(() => {
|
||||
service = new EsSearchService(coreMock.createPluginInitializerContext());
|
||||
mockCoreSetup = coreMock.createSetup();
|
||||
});
|
||||
|
||||
describe('setup()', () => {
|
||||
it('registers the ES search strategy', async () => {
|
||||
service.setup(mockCoreSetup, {
|
||||
search: searchSetupMock,
|
||||
});
|
||||
expect(searchSetupMock.registerSearchStrategyProvider).toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* 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 { Plugin, CoreSetup, PluginInitializerContext } from '../../../../../core/public';
|
||||
import { ES_SEARCH_STRATEGY } from '../../../common/search/es_search';
|
||||
import { esSearchStrategyProvider } from './es_search_strategy';
|
||||
import { ISearchSetup } from '../i_search_setup';
|
||||
|
||||
export interface IEsSearchSetupDependencies {
|
||||
search: ISearchSetup;
|
||||
}
|
||||
|
||||
export class EsSearchService implements Plugin {
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
public setup(core: CoreSetup, deps: IEsSearchSetupDependencies) {
|
||||
deps.search.registerSearchStrategyProvider(
|
||||
this.initializerContext.opaqueId,
|
||||
ES_SEARCH_STRATEGY,
|
||||
esSearchStrategyProvider
|
||||
);
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public stop() {}
|
||||
}
|
|
@ -19,15 +19,15 @@
|
|||
|
||||
import { coreMock } from '../../../../../core/public/mocks';
|
||||
import { esSearchStrategyProvider } from './es_search_strategy';
|
||||
import { CoreSetup } from 'kibana/public';
|
||||
import { CoreStart } from 'kibana/public';
|
||||
import { ES_SEARCH_STRATEGY } from '../../../common/search/es_search';
|
||||
|
||||
describe('ES search strategy', () => {
|
||||
let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
let mockCoreStart: MockedKeys<CoreStart>;
|
||||
const mockSearch = jest.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
mockCoreSetup = coreMock.createSetup();
|
||||
mockCoreStart = coreMock.createStart();
|
||||
mockSearch.mockClear();
|
||||
});
|
||||
|
||||
|
@ -35,12 +35,16 @@ describe('ES search strategy', () => {
|
|||
const request = { params: {} };
|
||||
const options = {};
|
||||
|
||||
const esSearch = esSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
},
|
||||
mockSearch
|
||||
);
|
||||
const esSearch = esSearchStrategyProvider({
|
||||
core: mockCoreStart,
|
||||
getSearchStrategy: jest.fn().mockImplementation(() => {
|
||||
return () => {
|
||||
return {
|
||||
search: mockSearch,
|
||||
};
|
||||
};
|
||||
}),
|
||||
});
|
||||
esSearch.search(request, options);
|
||||
|
||||
expect(mockSearch.mock.calls[0][0]).toEqual({
|
||||
|
|
|
@ -21,11 +21,10 @@ import { Observable } from 'rxjs';
|
|||
import { ES_SEARCH_STRATEGY, IEsSearchResponse } from '../../../common/search';
|
||||
import { SYNC_SEARCH_STRATEGY } from '../sync_search_strategy';
|
||||
import { getEsPreference } from './get_es_preference';
|
||||
import { TSearchStrategyProvider, ISearchStrategy, ISearchGeneric, ISearchContext } from '..';
|
||||
import { ISearchContext, TSearchStrategyProvider, ISearchStrategy } from '../types';
|
||||
|
||||
export const esSearchStrategyProvider: TSearchStrategyProvider<typeof ES_SEARCH_STRATEGY> = (
|
||||
context: ISearchContext,
|
||||
search: ISearchGeneric
|
||||
context: ISearchContext
|
||||
): ISearchStrategy<typeof ES_SEARCH_STRATEGY> => {
|
||||
return {
|
||||
search: (request, options) => {
|
||||
|
@ -34,10 +33,10 @@ export const esSearchStrategyProvider: TSearchStrategyProvider<typeof ES_SEARCH_
|
|||
const customPreference = context.core.uiSettings.get('courier:customRequestPreference');
|
||||
request.params.preference = getEsPreference(setPreference, customPreference);
|
||||
}
|
||||
return search(
|
||||
const syncStrategyProvider = context.getSearchStrategy(SYNC_SEARCH_STRATEGY);
|
||||
return syncStrategyProvider(context).search(
|
||||
{ ...request, serverStrategy: ES_SEARCH_STRATEGY },
|
||||
options,
|
||||
SYNC_SEARCH_STRATEGY
|
||||
options
|
||||
) as Observable<IEsSearchResponse>;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* 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 { coreMock } from '../../../../../../src/core/public/mocks';
|
||||
import { esSearchService } from '.';
|
||||
|
||||
it('es search service is instantiated', () => {
|
||||
const esSearch = esSearchService(coreMock.createPluginInitializerContext());
|
||||
expect(esSearch).toBeDefined();
|
||||
});
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* 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 { PluginInitializer, PluginInitializerContext } from 'kibana/public';
|
||||
import { EsSearchService } from './es_search_service';
|
||||
|
||||
export const esSearchService: PluginInitializer<void, void> = (
|
||||
initializerContext: PluginInitializerContext
|
||||
) => new EsSearchService(initializerContext);
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* 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 } from '../../../../core/public';
|
||||
|
||||
export interface ISearchContext {
|
||||
core: CoreSetup;
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* 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 { IContextProvider } from 'kibana/public';
|
||||
import { ISearchContext } from './i_search_context';
|
||||
import { TRegisterSearchStrategyProvider, TSearchStrategyProvider } from './i_search_strategy';
|
||||
|
||||
/**
|
||||
* The setup contract exposed by the Search plugin exposes the search strategy extension
|
||||
* point.
|
||||
*/
|
||||
export interface ISearchSetup {
|
||||
registerSearchStrategyContext: <TContextName extends keyof ISearchContext>(
|
||||
pluginId: symbol,
|
||||
contextName: TContextName,
|
||||
provider: IContextProvider<TSearchStrategyProvider<any>, TContextName>
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* Extension point exposed for other plugins to register their own search
|
||||
* strategies.
|
||||
*/
|
||||
registerSearchStrategyProvider: TRegisterSearchStrategyProvider;
|
||||
}
|
|
@ -17,12 +17,13 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export { ISearchAppMountContext } from './i_search_app_mount_context';
|
||||
|
||||
export { ISearchSetup } from './i_search_setup';
|
||||
export { ISearchStart } from './search_service';
|
||||
|
||||
export { ISearchContext } from './i_search_context';
|
||||
export {
|
||||
ISearchSetup,
|
||||
ISearchStart,
|
||||
ISearchContext,
|
||||
TSearchStrategyProvider,
|
||||
ISearchStrategy,
|
||||
} from './types';
|
||||
|
||||
export {
|
||||
ISearch,
|
||||
|
@ -32,8 +33,6 @@ export {
|
|||
ISearchGeneric,
|
||||
} from './i_search';
|
||||
|
||||
export { TSearchStrategyProvider, ISearchStrategy } from './i_search_strategy';
|
||||
|
||||
export { IEsSearchResponse, IEsSearchRequest, ES_SEARCH_STRATEGY } from '../../common/search';
|
||||
|
||||
export { SYNC_SEARCH_STRATEGY } from './sync_search_strategy';
|
||||
|
|
|
@ -27,7 +27,7 @@ describe('Search service', () => {
|
|||
let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
|
||||
beforeEach(() => {
|
||||
searchService = new SearchService(coreMock.createPluginInitializerContext());
|
||||
searchService = new SearchService();
|
||||
mockCoreSetup = coreMock.createSetup();
|
||||
});
|
||||
|
||||
|
@ -36,7 +36,6 @@ describe('Search service', () => {
|
|||
const setup = searchService.setup(mockCoreSetup, {
|
||||
version: '8',
|
||||
} as any);
|
||||
expect(setup).toHaveProperty('registerSearchStrategyContext');
|
||||
expect(setup).toHaveProperty('registerSearchStrategyProvider');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,46 +16,15 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
Plugin,
|
||||
CoreSetup,
|
||||
PluginInitializerContext,
|
||||
CoreStart,
|
||||
IContextContainer,
|
||||
PluginOpaqueId,
|
||||
PackageInfo,
|
||||
} from '../../../../core/public';
|
||||
|
||||
import { ISearchAppMountContext } from './i_search_app_mount_context';
|
||||
import { ISearchSetup } from './i_search_setup';
|
||||
import { createAppMountSearchContext } from './create_app_mount_context_search';
|
||||
import { Plugin, CoreSetup, CoreStart, PackageInfo } from '../../../../core/public';
|
||||
|
||||
import { SYNC_SEARCH_STRATEGY, syncSearchStrategyProvider } from './sync_search_strategy';
|
||||
import {
|
||||
TSearchStrategyProvider,
|
||||
TRegisterSearchStrategyProvider,
|
||||
TSearchStrategiesMap,
|
||||
} from './i_search_strategy';
|
||||
import { ISearchSetup, ISearchStart, TSearchStrategyProvider, TSearchStrategiesMap } from './types';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
import { esSearchService } from './es_search';
|
||||
import { ISearchGeneric } from './i_search';
|
||||
import { getEsClient, LegacyApiCaller } from './es_client';
|
||||
|
||||
/**
|
||||
* Extends the AppMountContext so other plugins have access
|
||||
* to search functionality in their applications.
|
||||
*/
|
||||
declare module 'kibana/public' {
|
||||
interface AppMountContext {
|
||||
search?: ISearchAppMountContext;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ISearchStart {
|
||||
search: ISearchGeneric;
|
||||
__LEGACY: {
|
||||
esClient: LegacyApiCaller;
|
||||
};
|
||||
}
|
||||
import { ES_SEARCH_STRATEGY, DEFAULT_SEARCH_STRATEGY } from '../../common/search';
|
||||
import { esSearchStrategyProvider } from './es_search/es_search_strategy';
|
||||
|
||||
/**
|
||||
* The search plugin exposes two registration methods for other plugins:
|
||||
|
@ -73,63 +42,43 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
*/
|
||||
private searchStrategies: TSearchStrategiesMap = {};
|
||||
|
||||
/**
|
||||
* Exposes context to the search strategies.
|
||||
*/
|
||||
private contextContainer?: IContextContainer<TSearchStrategyProvider<any>>;
|
||||
private esClient?: LegacyApiCaller;
|
||||
private search?: ISearchGeneric;
|
||||
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
private registerSearchStrategyProvider = <T extends TStrategyTypes>(
|
||||
name: T,
|
||||
strategyProvider: TSearchStrategyProvider<T>
|
||||
) => {
|
||||
this.searchStrategies[name] = strategyProvider;
|
||||
};
|
||||
|
||||
private getSearchStrategy = <T extends TStrategyTypes>(name: T): TSearchStrategyProvider<T> => {
|
||||
const strategyProvider = this.searchStrategies[name];
|
||||
if (!strategyProvider) throw new Error(`Search strategy ${name} not found`);
|
||||
return strategyProvider;
|
||||
};
|
||||
|
||||
public setup(core: CoreSetup, packageInfo: PackageInfo): ISearchSetup {
|
||||
const search = (this.search = createAppMountSearchContext(this.searchStrategies).search);
|
||||
core.application.registerMountContext<'search'>('search', () => {
|
||||
return { search };
|
||||
});
|
||||
|
||||
this.contextContainer = core.context.createContextContainer();
|
||||
this.esClient = getEsClient(core.injectedMetadata, core.http, packageInfo);
|
||||
|
||||
const registerSearchStrategyProvider: TRegisterSearchStrategyProvider = <
|
||||
T extends TStrategyTypes
|
||||
>(
|
||||
plugin: PluginOpaqueId,
|
||||
name: T,
|
||||
strategyProvider: TSearchStrategyProvider<T>
|
||||
) => {
|
||||
this.searchStrategies[name] = this.contextContainer!.createHandler(plugin, strategyProvider);
|
||||
this.registerSearchStrategyProvider(SYNC_SEARCH_STRATEGY, syncSearchStrategyProvider);
|
||||
|
||||
this.registerSearchStrategyProvider(ES_SEARCH_STRATEGY, esSearchStrategyProvider);
|
||||
|
||||
return {
|
||||
registerSearchStrategyProvider: this.registerSearchStrategyProvider,
|
||||
};
|
||||
|
||||
const api = {
|
||||
registerSearchStrategyContext: this.contextContainer!.registerContext,
|
||||
registerSearchStrategyProvider,
|
||||
__LEGACY: {
|
||||
esClient: this.esClient,
|
||||
},
|
||||
};
|
||||
|
||||
api.registerSearchStrategyContext(this.initializerContext.opaqueId, 'core', () => core);
|
||||
api.registerSearchStrategyProvider(
|
||||
this.initializerContext.opaqueId,
|
||||
SYNC_SEARCH_STRATEGY,
|
||||
syncSearchStrategyProvider
|
||||
);
|
||||
|
||||
// ES search capabilities are written in a way that it could easily be a separate plugin,
|
||||
// however these two plugins are tightly coupled due to the default search strategy using
|
||||
// es search types.
|
||||
esSearchService(this.initializerContext).setup(core, { search: api });
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
public start(core: CoreStart): ISearchStart {
|
||||
if (!this.search) {
|
||||
throw new Error('Search should always be defined');
|
||||
}
|
||||
return {
|
||||
search: this.search,
|
||||
search: (request, options, strategyName) => {
|
||||
const strategyProvider = this.getSearchStrategy(strategyName || DEFAULT_SEARCH_STRATEGY);
|
||||
const { search } = strategyProvider({
|
||||
core,
|
||||
getSearchStrategy: this.getSearchStrategy,
|
||||
});
|
||||
return search(request as any, options);
|
||||
},
|
||||
__LEGACY: {
|
||||
esClient: this.esClient!,
|
||||
},
|
||||
|
|
|
@ -19,32 +19,29 @@
|
|||
|
||||
import { coreMock } from '../../../../core/public/mocks';
|
||||
import { SYNC_SEARCH_STRATEGY, syncSearchStrategyProvider } from './sync_search_strategy';
|
||||
import { CoreSetup } from '../../../../core/public';
|
||||
import { CoreStart } from 'kibana/public';
|
||||
|
||||
describe('Sync search strategy', () => {
|
||||
let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
const mockSearch = jest.fn();
|
||||
let mockCoreStart: MockedKeys<CoreStart>;
|
||||
|
||||
beforeEach(() => {
|
||||
mockCoreSetup = coreMock.createSetup();
|
||||
mockCoreStart = coreMock.createStart();
|
||||
});
|
||||
|
||||
it('returns a strategy with `search` that calls the backend API', () => {
|
||||
mockCoreSetup.http.fetch.mockImplementationOnce(() => Promise.resolve());
|
||||
mockCoreStart.http.fetch.mockImplementationOnce(() => Promise.resolve());
|
||||
|
||||
const syncSearch = syncSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
},
|
||||
mockSearch
|
||||
);
|
||||
const syncSearch = syncSearchStrategyProvider({
|
||||
core: mockCoreStart,
|
||||
getSearchStrategy: jest.fn(),
|
||||
});
|
||||
syncSearch.search(
|
||||
{
|
||||
serverStrategy: SYNC_SEARCH_STRATEGY,
|
||||
},
|
||||
{}
|
||||
);
|
||||
expect(mockCoreSetup.http.fetch.mock.calls[0][0]).toEqual({
|
||||
expect(mockCoreStart.http.fetch.mock.calls[0][0]).toEqual({
|
||||
path: `/internal/search/${SYNC_SEARCH_STRATEGY}`,
|
||||
body: JSON.stringify({
|
||||
serverStrategy: 'SYNC_SEARCH_STRATEGY',
|
||||
|
|
|
@ -19,9 +19,8 @@
|
|||
|
||||
import { BehaviorSubject, from } from 'rxjs';
|
||||
import { IKibanaSearchRequest, IKibanaSearchResponse } from '../../common/search';
|
||||
import { ISearchContext } from './i_search_context';
|
||||
import { ISearch, ISearchOptions } from './i_search';
|
||||
import { TSearchStrategyProvider, ISearchStrategy } from './i_search_strategy';
|
||||
import { TSearchStrategyProvider, ISearchStrategy, ISearchContext } from './types';
|
||||
|
||||
export const SYNC_SEARCH_STRATEGY = 'SYNC_SEARCH_STRATEGY';
|
||||
|
||||
|
|
|
@ -17,9 +17,15 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { CoreStart } from 'kibana/public';
|
||||
import { ISearch, ISearchGeneric } from './i_search';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
import { ISearchContext } from './i_search_context';
|
||||
import { LegacyApiCaller } from './es_client';
|
||||
|
||||
export interface ISearchContext {
|
||||
core: CoreStart;
|
||||
getSearchStrategy: <T extends TStrategyTypes>(name: T) => TSearchStrategyProvider<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search strategy interface contains a search method that takes in
|
||||
|
@ -38,14 +44,17 @@ export type TSearchStrategyProviderEnhanced<T extends TStrategyTypes> = (
|
|||
search: ISearchGeneric
|
||||
) => Promise<ISearchStrategy<T>>;
|
||||
|
||||
export type TSearchStrategiesMap = {
|
||||
[K in TStrategyTypes]?: TSearchStrategyProvider<any>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Search strategy provider creates an instance of a search strategy with the request
|
||||
* handler context bound to it. This way every search strategy can use
|
||||
* whatever information they require from the request context.
|
||||
*/
|
||||
export type TSearchStrategyProvider<T extends TStrategyTypes> = (
|
||||
context: ISearchContext,
|
||||
search: ISearchGeneric
|
||||
context: ISearchContext
|
||||
) => ISearchStrategy<T>;
|
||||
|
||||
/**
|
||||
|
@ -53,11 +62,25 @@ export type TSearchStrategyProvider<T extends TStrategyTypes> = (
|
|||
* strategies.
|
||||
*/
|
||||
export type TRegisterSearchStrategyProvider = <T extends TStrategyTypes>(
|
||||
opaqueId: symbol,
|
||||
name: T,
|
||||
searchStrategyProvider: TSearchStrategyProvider<T>
|
||||
) => void;
|
||||
|
||||
export type TSearchStrategiesMap = {
|
||||
[K in TStrategyTypes]?: TSearchStrategyProviderEnhanced<K>;
|
||||
};
|
||||
/**
|
||||
* The setup contract exposed by the Search plugin exposes the search strategy extension
|
||||
* point.
|
||||
*/
|
||||
export interface ISearchSetup {
|
||||
/**
|
||||
* Extension point exposed for other plugins to register their own search
|
||||
* strategies.
|
||||
*/
|
||||
registerSearchStrategyProvider: TRegisterSearchStrategyProvider;
|
||||
}
|
||||
|
||||
export interface ISearchStart {
|
||||
search: ISearchGeneric;
|
||||
__LEGACY: {
|
||||
esClient: LegacyApiCaller;
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue