mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
* [search] Refactor the way search strategies are registered/retrieved on the server * Fix types and tests and update docs * Fix failing test * Fix build of example plugin * Fix functional test * Make server strategies sync Co-authored-by: Liza K <liza.katz@elastic.co> Co-authored-by: Lukas Olson <olson.lukas@gmail.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
fea77cd5ff
commit
48278a7c28
52 changed files with 550 additions and 739 deletions
|
@ -4,6 +4,8 @@
|
|||
|
||||
## IRequestTypesMap interface
|
||||
|
||||
The map of search strategy IDs to the corresponding request type definitions.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
## IResponseTypesMap interface
|
||||
|
||||
The map of search strategy IDs to the corresponding response type definitions.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type ISearch<T extends TStrategyTypes> = (request: IRequestTypesMap[T], options?: ISearchOptions) => Promise<IResponseTypesMap[T]>;
|
||||
export declare type ISearch<T extends TStrategyTypes> = (context: RequestHandlerContext, request: IRequestTypesMap[T], options?: ISearchOptions) => Promise<IResponseTypesMap[T]>;
|
||||
```
|
||||
|
|
|
@ -7,5 +7,5 @@
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type ISearchCancel<T extends TStrategyTypes> = (id: string) => Promise<void>;
|
||||
export declare type ISearchCancel<T extends TStrategyTypes> = (context: RequestHandlerContext, id: string) => Promise<void>;
|
||||
```
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchContext](./kibana-plugin-plugins-data-server.isearchcontext.md) > [config$](./kibana-plugin-plugins-data-server.isearchcontext.config_.md)
|
||||
|
||||
## ISearchContext.config$ property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
config$: Observable<SharedGlobalConfig>;
|
||||
```
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchContext](./kibana-plugin-plugins-data-server.isearchcontext.md) > [core](./kibana-plugin-plugins-data-server.isearchcontext.core.md)
|
||||
|
||||
## ISearchContext.core property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
core: CoreSetup;
|
||||
```
|
|
@ -1,19 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchContext](./kibana-plugin-plugins-data-server.isearchcontext.md)
|
||||
|
||||
## ISearchContext interface
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface ISearchContext
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [config$](./kibana-plugin-plugins-data-server.isearchcontext.config_.md) | <code>Observable<SharedGlobalConfig></code> | |
|
||||
| [core](./kibana-plugin-plugins-data-server.isearchcontext.core.md) | <code>CoreSetup</code> | |
|
||||
|
|
@ -14,5 +14,5 @@ export interface ISearchOptions
|
|||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [signal](./kibana-plugin-plugins-data-server.isearchoptions.signal.md) | <code>AbortSignal</code> | |
|
||||
| [signal](./kibana-plugin-plugins-data-server.isearchoptions.signal.md) | <code>AbortSignal</code> | An <code>AbortSignal</code> that allows the caller of <code>search</code> to abort a search request. |
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
## ISearchOptions.signal property
|
||||
|
||||
An `AbortSignal` that allows the caller of `search` to abort a search request.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchSetup](./kibana-plugin-plugins-data-server.isearchsetup.md)
|
||||
|
||||
## ISearchSetup interface
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface ISearchSetup
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [registerSearchStrategy](./kibana-plugin-plugins-data-server.isearchsetup.registersearchstrategy.md) | <code>TRegisterSearchStrategy</code> | Extension point exposed for other plugins to register their own search strategies. |
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchSetup](./kibana-plugin-plugins-data-server.isearchsetup.md) > [registerSearchStrategy](./kibana-plugin-plugins-data-server.isearchsetup.registersearchstrategy.md)
|
||||
|
||||
## ISearchSetup.registerSearchStrategy property
|
||||
|
||||
Extension point exposed for other plugins to register their own search strategies.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
registerSearchStrategy: TRegisterSearchStrategy;
|
||||
```
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchStart](./kibana-plugin-plugins-data-server.isearchstart.md) > [getSearchStrategy](./kibana-plugin-plugins-data-server.isearchstart.getsearchstrategy.md)
|
||||
|
||||
## ISearchStart.getSearchStrategy property
|
||||
|
||||
Get other registered search strategies. For example, if a new strategy needs to use the already-registered ES search strategy, it can use this function to accomplish that.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getSearchStrategy: TGetSearchStrategy;
|
||||
```
|
|
@ -0,0 +1,18 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchStart](./kibana-plugin-plugins-data-server.isearchstart.md)
|
||||
|
||||
## ISearchStart interface
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface ISearchStart
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [getSearchStrategy](./kibana-plugin-plugins-data-server.isearchstart.getsearchstrategy.md) | <code>TGetSearchStrategy</code> | Get other registered search strategies. For example, if a new strategy needs to use the already-registered ES search strategy, it can use this function to accomplish that. |
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchStrategy](./kibana-plugin-plugins-data-server.isearchstrategy.md) > [cancel](./kibana-plugin-plugins-data-server.isearchstrategy.cancel.md)
|
||||
|
||||
## ISearchStrategy.cancel property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
cancel?: ISearchCancel<T>;
|
||||
```
|
|
@ -0,0 +1,21 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchStrategy](./kibana-plugin-plugins-data-server.isearchstrategy.md)
|
||||
|
||||
## ISearchStrategy interface
|
||||
|
||||
Search strategy interface contains a search method that takes in a request and returns a promise that resolves to a response.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface ISearchStrategy<T extends TStrategyTypes>
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [cancel](./kibana-plugin-plugins-data-server.isearchstrategy.cancel.md) | <code>ISearchCancel<T></code> | |
|
||||
| [search](./kibana-plugin-plugins-data-server.isearchstrategy.search.md) | <code>ISearch<T></code> | |
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [ISearchStrategy](./kibana-plugin-plugins-data-server.isearchstrategy.md) > [search](./kibana-plugin-plugins-data-server.isearchstrategy.search.md)
|
||||
|
||||
## ISearchStrategy.search property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
search: ISearch<T>;
|
||||
```
|
|
@ -39,10 +39,12 @@
|
|||
| [IIndexPattern](./kibana-plugin-plugins-data-server.iindexpattern.md) | |
|
||||
| [IndexPatternAttributes](./kibana-plugin-plugins-data-server.indexpatternattributes.md) | Use data plugin interface instead |
|
||||
| [IndexPatternFieldDescriptor](./kibana-plugin-plugins-data-server.indexpatternfielddescriptor.md) | |
|
||||
| [IRequestTypesMap](./kibana-plugin-plugins-data-server.irequesttypesmap.md) | |
|
||||
| [IResponseTypesMap](./kibana-plugin-plugins-data-server.iresponsetypesmap.md) | |
|
||||
| [ISearchContext](./kibana-plugin-plugins-data-server.isearchcontext.md) | |
|
||||
| [IRequestTypesMap](./kibana-plugin-plugins-data-server.irequesttypesmap.md) | The map of search strategy IDs to the corresponding request type definitions. |
|
||||
| [IResponseTypesMap](./kibana-plugin-plugins-data-server.iresponsetypesmap.md) | The map of search strategy IDs to the corresponding response type definitions. |
|
||||
| [ISearchOptions](./kibana-plugin-plugins-data-server.isearchoptions.md) | |
|
||||
| [ISearchSetup](./kibana-plugin-plugins-data-server.isearchsetup.md) | |
|
||||
| [ISearchStart](./kibana-plugin-plugins-data-server.isearchstart.md) | |
|
||||
| [ISearchStrategy](./kibana-plugin-plugins-data-server.isearchstrategy.md) | Search strategy interface contains a search method that takes in a request and returns a promise that resolves to a response. |
|
||||
| [KueryNode](./kibana-plugin-plugins-data-server.kuerynode.md) | |
|
||||
| [PluginSetup](./kibana-plugin-plugins-data-server.pluginsetup.md) | |
|
||||
| [PluginStart](./kibana-plugin-plugins-data-server.pluginstart.md) | |
|
||||
|
@ -73,5 +75,5 @@
|
|||
| [ISearch](./kibana-plugin-plugins-data-server.isearch.md) | |
|
||||
| [ISearchCancel](./kibana-plugin-plugins-data-server.isearchcancel.md) | |
|
||||
| [ParsedInterval](./kibana-plugin-plugins-data-server.parsedinterval.md) | |
|
||||
| [TSearchStrategyProvider](./kibana-plugin-plugins-data-server.tsearchstrategyprovider.md) | 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. |
|
||||
| [TStrategyTypes](./kibana-plugin-plugins-data-server.tstrategytypes.md) | Contains all known strategy type identifiers that will be used to map to request and response shapes. Plugins that wish to add their own custom search strategies should extend this type via:<!-- -->const MY\_STRATEGY = 'MY\_STRATEGY';<!-- -->declare module 'src/plugins/search/server' { export interface IRequestTypesMap { \[MY\_STRATEGY\]: IMySearchRequest; }<!-- -->export interface IResponseTypesMap { \[MY\_STRATEGY\]: IMySearchResponse } } |
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
setup(core: CoreSetup, { usageCollection }: DataPluginSetupDependencies): {
|
||||
setup(core: CoreSetup<object, DataPluginStart>, { usageCollection }: DataPluginSetupDependencies): {
|
||||
search: ISearchSetup;
|
||||
fieldFormats: {
|
||||
register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number;
|
||||
};
|
||||
search: ISearchSetup;
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -19,15 +19,15 @@ setup(core: CoreSetup, { usageCollection }: DataPluginSetupDependencies): {
|
|||
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| core | <code>CoreSetup</code> | |
|
||||
| core | <code>CoreSetup<object, DataPluginStart></code> | |
|
||||
| { usageCollection } | <code>DataPluginSetupDependencies</code> | |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
`{
|
||||
search: ISearchSetup;
|
||||
fieldFormats: {
|
||||
register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number;
|
||||
};
|
||||
search: ISearchSetup;
|
||||
}`
|
||||
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
|
||||
```typescript
|
||||
start(core: CoreStart): {
|
||||
search: ISearchStart;
|
||||
fieldFormats: {
|
||||
fieldFormatServiceFactory: (uiSettings: import("kibana/server").IUiSettingsClient) => Promise<import("../common").FieldFormatsRegistry>;
|
||||
fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise<import("../common").FieldFormatsRegistry>;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
@ -23,8 +24,9 @@ start(core: CoreStart): {
|
|||
<b>Returns:</b>
|
||||
|
||||
`{
|
||||
search: ISearchStart;
|
||||
fieldFormats: {
|
||||
fieldFormatServiceFactory: (uiSettings: import("kibana/server").IUiSettingsClient) => Promise<import("../common").FieldFormatsRegistry>;
|
||||
fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise<import("../common").FieldFormatsRegistry>;
|
||||
};
|
||||
}`
|
||||
|
||||
|
|
|
@ -15,4 +15,5 @@ export interface DataPluginStart
|
|||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [fieldFormats](./kibana-plugin-plugins-data-server.pluginstart.fieldformats.md) | <code>FieldFormatsStart</code> | |
|
||||
| [search](./kibana-plugin-plugins-data-server.pluginstart.search.md) | <code>ISearchStart</code> | |
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [PluginStart](./kibana-plugin-plugins-data-server.pluginstart.md) > [search](./kibana-plugin-plugins-data-server.pluginstart.search.md)
|
||||
|
||||
## PluginStart.search property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
search: ISearchStart;
|
||||
```
|
|
@ -1,13 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [TSearchStrategyProvider](./kibana-plugin-plugins-data-server.tsearchstrategyprovider.md)
|
||||
|
||||
## TSearchStrategyProvider type
|
||||
|
||||
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.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type TSearchStrategyProvider<T extends TStrategyTypes> = (context: ISearchContext, caller: APICaller, search: ISearchGeneric) => ISearchStrategy<T>;
|
||||
```
|
|
@ -0,0 +1,19 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [TStrategyTypes](./kibana-plugin-plugins-data-server.tstrategytypes.md)
|
||||
|
||||
## TStrategyTypes type
|
||||
|
||||
Contains all known strategy type identifiers that will be used to map to request and response shapes. Plugins that wish to add their own custom search strategies should extend this type via:
|
||||
|
||||
const MY\_STRATEGY = 'MY\_STRATEGY';
|
||||
|
||||
declare module 'src/plugins/search/server' { export interface IRequestTypesMap { \[MY\_STRATEGY\]: IMySearchRequest; }
|
||||
|
||||
export interface IResponseTypesMap { \[MY\_STRATEGY\]: IMySearchResponse } }
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export declare type TStrategyTypes = typeof ES_SEARCH_STRATEGY | string;
|
||||
```
|
|
@ -17,30 +17,32 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { TSearchStrategyProvider } from '../../../src/plugins/data/server';
|
||||
import { ASYNC_DEMO_SEARCH_STRATEGY } from '../common';
|
||||
import { ISearchStrategy } from '../../../src/plugins/data/server';
|
||||
import { ASYNC_DEMO_SEARCH_STRATEGY, IAsyncDemoRequest } from '../common';
|
||||
|
||||
function getFibonacciSequence(n = 0) {
|
||||
const beginning = [0, 1].slice(0, n);
|
||||
return Array(Math.max(0, n))
|
||||
.fill(null)
|
||||
.reduce((sequence, value, i) => {
|
||||
if (i < 2) return sequence;
|
||||
return [...sequence, sequence[i - 1] + sequence[i - 2]];
|
||||
}, beginning);
|
||||
}
|
||||
export const asyncDemoSearchStrategyProvider = (): ISearchStrategy<
|
||||
typeof ASYNC_DEMO_SEARCH_STRATEGY
|
||||
> => {
|
||||
function getFibonacciSequence(n = 0) {
|
||||
const beginning = [0, 1].slice(0, n);
|
||||
return Array(Math.max(0, n))
|
||||
.fill(null)
|
||||
.reduce((sequence, value, i) => {
|
||||
if (i < 2) return sequence;
|
||||
return [...sequence, sequence[i - 1] + sequence[i - 2]];
|
||||
}, beginning);
|
||||
}
|
||||
|
||||
const generateId = (() => {
|
||||
let id = 0;
|
||||
return () => `${id++}`;
|
||||
})();
|
||||
const generateId = (() => {
|
||||
let id = 0;
|
||||
return () => `${id++}`;
|
||||
})();
|
||||
|
||||
const loadedMap = new Map<string, number>();
|
||||
const totalMap = new Map<string, number>();
|
||||
const loadedMap = new Map<string, number>();
|
||||
const totalMap = new Map<string, number>();
|
||||
|
||||
export const asyncDemoSearchStrategyProvider: TSearchStrategyProvider<typeof ASYNC_DEMO_SEARCH_STRATEGY> = () => {
|
||||
return {
|
||||
search: async (request) => {
|
||||
search: async (context, request: IAsyncDemoRequest) => {
|
||||
const id = request.id ?? generateId();
|
||||
|
||||
const loaded = (loadedMap.get(id) ?? 0) + 1;
|
||||
|
@ -52,7 +54,7 @@ export const asyncDemoSearchStrategyProvider: TSearchStrategyProvider<typeof ASY
|
|||
const fibonacciSequence = getFibonacciSequence(loaded);
|
||||
return { id, total, loaded, fibonacciSequence };
|
||||
},
|
||||
cancel: async (id) => {
|
||||
cancel: async (context, id) => {
|
||||
loadedMap.delete(id);
|
||||
totalMap.delete(id);
|
||||
},
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { TSearchStrategyProvider } from '../../../src/plugins/data/server';
|
||||
import { DEMO_SEARCH_STRATEGY } from '../common';
|
||||
import { ISearchStrategy } from '../../../src/plugins/data/server';
|
||||
import { DEMO_SEARCH_STRATEGY, IDemoRequest } from '../common';
|
||||
|
||||
export const demoSearchStrategyProvider: TSearchStrategyProvider<typeof DEMO_SEARCH_STRATEGY> = () => {
|
||||
export const demoSearchStrategyProvider = (): ISearchStrategy<typeof DEMO_SEARCH_STRATEGY> => {
|
||||
return {
|
||||
search: (request) => {
|
||||
search: (context, request: IDemoRequest) => {
|
||||
return Promise.resolve({
|
||||
greeting:
|
||||
request.mood === 'happy'
|
||||
|
|
|
@ -17,9 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { PluginInitializerContext, PluginInitializer } from 'kibana/server';
|
||||
import { DemoDataPlugin } from './plugin';
|
||||
|
||||
export const plugin: PluginInitializer<void, void> = (
|
||||
initializerContext: PluginInitializerContext
|
||||
) => new DemoDataPlugin(initializerContext);
|
||||
export const plugin = () => new DemoDataPlugin();
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { Plugin, CoreSetup, PluginInitializerContext } from 'kibana/server';
|
||||
import { Plugin, CoreSetup } from 'kibana/server';
|
||||
import { PluginSetup as DataPluginSetup } from 'src/plugins/data/server';
|
||||
import { demoSearchStrategyProvider } from './demo_search_strategy';
|
||||
import {
|
||||
|
@ -56,18 +56,13 @@ declare module '../../../src/plugins/data/server' {
|
|||
}
|
||||
|
||||
export class DemoDataPlugin implements Plugin<void, void, IDemoSearchExplorerDeps> {
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
constructor() {}
|
||||
|
||||
public setup(core: CoreSetup, deps: IDemoSearchExplorerDeps) {
|
||||
deps.data.search.registerSearchStrategyProvider(
|
||||
this.initializerContext.opaqueId,
|
||||
DEMO_SEARCH_STRATEGY,
|
||||
demoSearchStrategyProvider
|
||||
);
|
||||
deps.data.search.registerSearchStrategyProvider(
|
||||
this.initializerContext.opaqueId,
|
||||
deps.data.search.registerSearchStrategy(DEMO_SEARCH_STRATEGY, demoSearchStrategyProvider());
|
||||
deps.data.search.registerSearchStrategy(
|
||||
ASYNC_DEMO_SEARCH_STRATEGY,
|
||||
asyncDemoSearchStrategyProvider
|
||||
asyncDemoSearchStrategyProvider()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,11 +23,6 @@ import { GuideSection } from './guide_section';
|
|||
import publicSearch from '!!raw-loader!./../../../src/plugins/data/public/search/i_search';
|
||||
// @ts-ignore
|
||||
import publicPlugin from '!!raw-loader!./../../../src/plugins/data/public/search/search_service';
|
||||
|
||||
// @ts-ignore
|
||||
import serverSetupContract from '!!raw-loader!./../../../src/plugins/data/server/search/i_search_setup';
|
||||
// @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';
|
||||
|
||||
|
@ -54,14 +49,6 @@ export const SearchApiPage = () => (
|
|||
description: 'search_service.ts',
|
||||
snippet: serverPlugin,
|
||||
},
|
||||
{
|
||||
description: `i_search_setup.ts`,
|
||||
snippet: serverSetupContract,
|
||||
},
|
||||
{
|
||||
description: 'i_search',
|
||||
snippet: serverSearch,
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
|
|
|
@ -17,9 +17,14 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { ISearchGeneric, ISearchCancelGeneric } from './i_search';
|
||||
|
||||
export interface IRouteHandlerSearchContext {
|
||||
search: ISearchGeneric;
|
||||
cancel: ISearchCancelGeneric;
|
||||
export function createFieldFormatsSetupMock() {
|
||||
return {
|
||||
register: jest.fn(),
|
||||
};
|
||||
}
|
||||
|
||||
export function createFieldFormatsStartMock() {
|
||||
return {
|
||||
fieldFormatServiceFactory: jest.fn(),
|
||||
};
|
||||
}
|
|
@ -172,8 +172,10 @@ export {
|
|||
ISearchOptions,
|
||||
IRequestTypesMap,
|
||||
IResponseTypesMap,
|
||||
ISearchContext,
|
||||
TSearchStrategyProvider,
|
||||
ISearchSetup,
|
||||
ISearchStart,
|
||||
TStrategyTypes,
|
||||
ISearchStrategy,
|
||||
getDefaultSearchParams,
|
||||
getTotalLoaded,
|
||||
} from './search';
|
||||
|
|
|
@ -17,10 +17,24 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { CoreSetup, SharedGlobalConfig } from '../../../../core/server';
|
||||
import { createSearchSetupMock, createSearchStartMock } from './search/mocks';
|
||||
import { createFieldFormatsSetupMock, createFieldFormatsStartMock } from './field_formats/mocks';
|
||||
|
||||
export interface ISearchContext {
|
||||
core: CoreSetup;
|
||||
config$: Observable<SharedGlobalConfig>;
|
||||
function createSetupContract() {
|
||||
return {
|
||||
search: createSearchSetupMock(),
|
||||
fieldFormats: createFieldFormatsSetupMock(),
|
||||
};
|
||||
}
|
||||
|
||||
function createStartContract() {
|
||||
return {
|
||||
search: createSearchStartMock(),
|
||||
fieldFormats: createFieldFormatsStartMock(),
|
||||
};
|
||||
}
|
||||
|
||||
export const dataPluginMock = {
|
||||
createSetupContract,
|
||||
createStartContract,
|
||||
};
|
|
@ -20,7 +20,7 @@
|
|||
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/server';
|
||||
import { ConfigSchema } from '../config';
|
||||
import { IndexPatternsService } from './index_patterns';
|
||||
import { ISearchSetup } from './search';
|
||||
import { ISearchSetup, ISearchStart } from './search';
|
||||
import { SearchService } from './search/search_service';
|
||||
import { QueryService } from './query/query_service';
|
||||
import { ScriptsService } from './scripts';
|
||||
|
@ -36,6 +36,7 @@ export interface DataPluginSetup {
|
|||
}
|
||||
|
||||
export interface DataPluginStart {
|
||||
search: ISearchStart;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
}
|
||||
|
||||
|
@ -59,7 +60,10 @@ export class DataServerPlugin implements Plugin<DataPluginSetup, DataPluginStart
|
|||
this.autocompleteService = new AutocompleteService(initializerContext);
|
||||
}
|
||||
|
||||
public setup(core: CoreSetup, { usageCollection }: DataPluginSetupDependencies) {
|
||||
public setup(
|
||||
core: CoreSetup<object, DataPluginStart>,
|
||||
{ usageCollection }: DataPluginSetupDependencies
|
||||
) {
|
||||
this.indexPatterns.setup(core);
|
||||
this.scriptsService.setup(core);
|
||||
this.queryService.setup(core);
|
||||
|
@ -69,13 +73,14 @@ export class DataServerPlugin implements Plugin<DataPluginSetup, DataPluginStart
|
|||
core.uiSettings.register(getUiSettings());
|
||||
|
||||
return {
|
||||
fieldFormats: this.fieldFormats.setup(),
|
||||
search: this.searchService.setup(core),
|
||||
fieldFormats: this.fieldFormats.setup(),
|
||||
};
|
||||
}
|
||||
|
||||
public start(core: CoreStart) {
|
||||
return {
|
||||
search: this.searchService.start(),
|
||||
fieldFormats: this.fieldFormats.start(),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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 { createApi } from './create_api';
|
||||
|
||||
import { TSearchStrategiesMap } from './i_search_strategy';
|
||||
import { IRouteHandlerSearchContext } from './i_route_handler_search_context';
|
||||
import { DEFAULT_SEARCH_STRATEGY } from '../../common/search';
|
||||
|
||||
const mockDefaultSearch = jest.fn(() => Promise.resolve({ total: 100, loaded: 0 }));
|
||||
const mockDefaultSearchStrategyProvider = jest.fn(() =>
|
||||
Promise.resolve({
|
||||
search: mockDefaultSearch,
|
||||
})
|
||||
);
|
||||
const mockStrategies: TSearchStrategiesMap = {
|
||||
[DEFAULT_SEARCH_STRATEGY]: mockDefaultSearchStrategyProvider,
|
||||
};
|
||||
|
||||
describe('createApi', () => {
|
||||
let api: IRouteHandlerSearchContext;
|
||||
|
||||
beforeEach(() => {
|
||||
api = createApi({
|
||||
caller: jest.fn(),
|
||||
searchStrategies: mockStrategies,
|
||||
});
|
||||
mockDefaultSearchStrategyProvider.mockClear();
|
||||
});
|
||||
|
||||
it('should default to DEFAULT_SEARCH_STRATEGY if none is provided', async () => {
|
||||
await api.search({
|
||||
params: {},
|
||||
});
|
||||
expect(mockDefaultSearchStrategyProvider).toBeCalled();
|
||||
expect(mockDefaultSearch).toBeCalled();
|
||||
});
|
||||
|
||||
it('should throw if no provider is found for the given name', () => {
|
||||
expect(api.search({}, {}, 'noneByThisName')).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"No strategy found for noneByThisName"`
|
||||
);
|
||||
});
|
||||
|
||||
it('logs the response if `debug` is set to `true`', async () => {
|
||||
const spy = jest.spyOn(console, 'log');
|
||||
await api.search({ params: {} });
|
||||
|
||||
expect(spy).not.toBeCalled();
|
||||
|
||||
await api.search({ debug: true, params: {} });
|
||||
|
||||
expect(spy).toBeCalled();
|
||||
});
|
||||
});
|
|
@ -1,58 +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 { APICaller } from 'kibana/server';
|
||||
import { IRouteHandlerSearchContext } from './i_route_handler_search_context';
|
||||
import { DEFAULT_SEARCH_STRATEGY } from '../../common/search';
|
||||
import { TSearchStrategiesMap } from './i_search_strategy';
|
||||
|
||||
export function createApi({
|
||||
caller,
|
||||
searchStrategies,
|
||||
}: {
|
||||
searchStrategies: TSearchStrategiesMap;
|
||||
caller: APICaller;
|
||||
}) {
|
||||
const api: IRouteHandlerSearchContext = {
|
||||
search: async (request, options, strategyName) => {
|
||||
if (request.debug) {
|
||||
// eslint-disable-next-line
|
||||
console.log(JSON.stringify(request, null, 2));
|
||||
}
|
||||
const name = strategyName ?? DEFAULT_SEARCH_STRATEGY;
|
||||
const strategyProvider = searchStrategies[name];
|
||||
if (!strategyProvider) {
|
||||
throw new Error(`No strategy found for ${strategyName}`);
|
||||
}
|
||||
// Give providers access to other search strategies by injecting this function
|
||||
const strategy = await strategyProvider(caller, api.search);
|
||||
return strategy.search(request, options);
|
||||
},
|
||||
cancel: async (id, strategyName) => {
|
||||
const name = strategyName ?? DEFAULT_SEARCH_STRATEGY;
|
||||
const strategyProvider = searchStrategies[name];
|
||||
if (!strategyProvider) {
|
||||
throw new Error(`No strategy found for ${strategyName}`);
|
||||
}
|
||||
const strategy = await strategyProvider(caller, api.search);
|
||||
return strategy.cancel && strategy.cancel(id);
|
||||
},
|
||||
};
|
||||
return api;
|
||||
}
|
|
@ -17,11 +17,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { coreMock, pluginInitializerContextConfigMock } from '../../../../../core/server/mocks';
|
||||
import { RequestHandlerContext } from '../../../../../core/server';
|
||||
import { pluginInitializerContextConfigMock } from '../../../../../core/server/mocks';
|
||||
import { esSearchStrategyProvider } from './es_search_strategy';
|
||||
|
||||
describe('ES search strategy', () => {
|
||||
const mockCoreSetup = coreMock.createSetup();
|
||||
const mockApiCaller = jest.fn().mockResolvedValue({
|
||||
_shards: {
|
||||
total: 10,
|
||||
|
@ -30,39 +30,26 @@ describe('ES search strategy', () => {
|
|||
successful: 7,
|
||||
},
|
||||
});
|
||||
const mockSearch = jest.fn();
|
||||
const mockContext = {
|
||||
core: { elasticsearch: { legacy: { client: { callAsCurrentUser: mockApiCaller } } } },
|
||||
};
|
||||
const mockConfig$ = pluginInitializerContextConfigMock<any>({}).legacy.globalConfig$;
|
||||
|
||||
beforeEach(() => {
|
||||
mockApiCaller.mockClear();
|
||||
mockSearch.mockClear();
|
||||
});
|
||||
|
||||
it('returns a strategy with `search`', () => {
|
||||
const esSearch = esSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
config$: mockConfig$,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
it('returns a strategy with `search`', async () => {
|
||||
const esSearch = await esSearchStrategyProvider(mockConfig$);
|
||||
|
||||
expect(typeof esSearch.search).toBe('function');
|
||||
});
|
||||
|
||||
it('calls the API caller with the params with defaults', async () => {
|
||||
const params = { index: 'logstash-*' };
|
||||
const esSearch = esSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
config$: mockConfig$,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
const esSearch = await esSearchStrategyProvider(mockConfig$);
|
||||
|
||||
await esSearch.search({ params });
|
||||
await esSearch.search((mockContext as unknown) as RequestHandlerContext, { params });
|
||||
|
||||
expect(mockApiCaller).toBeCalled();
|
||||
expect(mockApiCaller.mock.calls[0][0]).toBe('search');
|
||||
|
@ -76,16 +63,9 @@ describe('ES search strategy', () => {
|
|||
|
||||
it('calls the API caller with overridden defaults', async () => {
|
||||
const params = { index: 'logstash-*', ignoreUnavailable: false, timeout: '1000ms' };
|
||||
const esSearch = esSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
config$: mockConfig$,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
const esSearch = await esSearchStrategyProvider(mockConfig$);
|
||||
|
||||
await esSearch.search({ params });
|
||||
await esSearch.search((mockContext as unknown) as RequestHandlerContext, { params });
|
||||
|
||||
expect(mockApiCaller).toBeCalled();
|
||||
expect(mockApiCaller.mock.calls[0][0]).toBe('search');
|
||||
|
@ -97,16 +77,11 @@ describe('ES search strategy', () => {
|
|||
|
||||
it('returns total, loaded, and raw response', async () => {
|
||||
const params = { index: 'logstash-*' };
|
||||
const esSearch = esSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
config$: mockConfig$,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
const esSearch = await esSearchStrategyProvider(mockConfig$);
|
||||
|
||||
const response = await esSearch.search({ params });
|
||||
const response = await esSearch.search((mockContext as unknown) as RequestHandlerContext, {
|
||||
params,
|
||||
});
|
||||
|
||||
expect(response).toHaveProperty('total');
|
||||
expect(response).toHaveProperty('loaded');
|
||||
|
|
|
@ -17,19 +17,18 @@
|
|||
* under the License.
|
||||
*/
|
||||
import { first } from 'rxjs/operators';
|
||||
import { APICaller } from 'kibana/server';
|
||||
import { RequestHandlerContext, SharedGlobalConfig } from 'kibana/server';
|
||||
import { SearchResponse } from 'elasticsearch';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ES_SEARCH_STRATEGY } from '../../../common/search';
|
||||
import { ISearchStrategy, TSearchStrategyProvider } from '../i_search_strategy';
|
||||
import { getDefaultSearchParams, getTotalLoaded, ISearchContext } from '..';
|
||||
import { ISearchStrategy, getDefaultSearchParams, getTotalLoaded } from '..';
|
||||
|
||||
export const esSearchStrategyProvider: TSearchStrategyProvider<typeof ES_SEARCH_STRATEGY> = (
|
||||
context: ISearchContext,
|
||||
caller: APICaller
|
||||
export const esSearchStrategyProvider = (
|
||||
config$: Observable<SharedGlobalConfig>
|
||||
): ISearchStrategy<typeof ES_SEARCH_STRATEGY> => {
|
||||
return {
|
||||
search: async (request, options) => {
|
||||
const config = await context.config$.pipe(first()).toPromise();
|
||||
search: async (context: RequestHandlerContext, request, options) => {
|
||||
const config = await config$.pipe(first()).toPromise();
|
||||
const defaultParams = getDefaultSearchParams(config);
|
||||
|
||||
// Only default index pattern type is supported here.
|
||||
|
@ -42,7 +41,12 @@ export const esSearchStrategyProvider: TSearchStrategyProvider<typeof ES_SEARCH_
|
|||
...defaultParams,
|
||||
...request.params,
|
||||
};
|
||||
const rawResponse = (await caller('search', params, options)) as SearchResponse<any>;
|
||||
|
||||
const rawResponse = (await context.core.elasticsearch.legacy.client.callAsCurrentUser(
|
||||
'search',
|
||||
params,
|
||||
options
|
||||
)) as SearchResponse<any>;
|
||||
|
||||
// The above query will either complete or timeout and throw an error.
|
||||
// There is no progress indication on this api.
|
||||
|
|
|
@ -1,55 +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 { IKibanaSearchResponse, IKibanaSearchRequest } from '../../common/search';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
import { ES_SEARCH_STRATEGY, IEsSearchResponse } from '../../common/search/es_search';
|
||||
import { IEsSearchRequest } from './es_search';
|
||||
|
||||
export interface ISearchOptions {
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
export interface IRequestTypesMap {
|
||||
[ES_SEARCH_STRATEGY]: IEsSearchRequest;
|
||||
[key: string]: IKibanaSearchRequest;
|
||||
}
|
||||
|
||||
export interface IResponseTypesMap {
|
||||
[ES_SEARCH_STRATEGY]: IEsSearchResponse;
|
||||
[key: string]: IKibanaSearchResponse;
|
||||
}
|
||||
|
||||
export type ISearchGeneric = <T extends TStrategyTypes = typeof ES_SEARCH_STRATEGY>(
|
||||
request: IRequestTypesMap[T],
|
||||
options?: ISearchOptions,
|
||||
strategy?: T
|
||||
) => Promise<IResponseTypesMap[T]>;
|
||||
|
||||
export type ISearchCancelGeneric = <T extends TStrategyTypes = typeof ES_SEARCH_STRATEGY>(
|
||||
id: string,
|
||||
strategy?: T
|
||||
) => Promise<void>;
|
||||
|
||||
export type ISearch<T extends TStrategyTypes> = (
|
||||
request: IRequestTypesMap[T],
|
||||
options?: ISearchOptions
|
||||
) => Promise<IResponseTypesMap[T]>;
|
||||
|
||||
export type ISearchCancel<T extends TStrategyTypes> = (id: string) => Promise<void>;
|
|
@ -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/server';
|
||||
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,
|
||||
strategyName: TContextName,
|
||||
provider: IContextProvider<TSearchStrategyProvider<any>, TContextName>
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* Extension point exposed for other plugins to register their own search
|
||||
* strategies.
|
||||
*/
|
||||
registerSearchStrategyProvider: TRegisterSearchStrategyProvider;
|
||||
}
|
|
@ -1,67 +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 { APICaller } from 'kibana/server';
|
||||
import { ISearch, ISearchCancel, ISearchGeneric } from './i_search';
|
||||
import { TStrategyTypes } from './strategy_types';
|
||||
import { ISearchContext } from './i_search_context';
|
||||
|
||||
/**
|
||||
* Search strategy interface contains a search method that takes in
|
||||
* a request and returns a promise that resolves to a response.
|
||||
*/
|
||||
export interface ISearchStrategy<T extends TStrategyTypes> {
|
||||
search: ISearch<T>;
|
||||
cancel?: ISearchCancel<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 TSearchStrategyProviderEnhanced<T extends TStrategyTypes> = (
|
||||
caller: APICaller,
|
||||
search: ISearchGeneric
|
||||
) => Promise<ISearchStrategy<T>>;
|
||||
|
||||
/**
|
||||
* 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,
|
||||
caller: APICaller,
|
||||
search: ISearchGeneric
|
||||
) => ISearchStrategy<T>;
|
||||
|
||||
/**
|
||||
* Extension point exposed for other plugins to register their own search
|
||||
* strategies.
|
||||
*/
|
||||
export type TRegisterSearchStrategyProvider = <T extends TStrategyTypes>(
|
||||
opaqueId: symbol,
|
||||
name: T,
|
||||
searchStrategyProvider: TSearchStrategyProvider<T>
|
||||
) => void;
|
||||
|
||||
export type TSearchStrategiesMap = {
|
||||
[K in TStrategyTypes]?: TSearchStrategyProviderEnhanced<K>;
|
||||
};
|
|
@ -17,20 +17,16 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export { ISearchSetup } from './i_search_setup';
|
||||
|
||||
export { ISearchContext } from './i_search_context';
|
||||
|
||||
export {
|
||||
ISearch,
|
||||
ISearchCancel,
|
||||
ISearchOptions,
|
||||
IRequestTypesMap,
|
||||
IResponseTypesMap,
|
||||
} from './i_search';
|
||||
|
||||
export { TStrategyTypes } from './strategy_types';
|
||||
|
||||
export { TSearchStrategyProvider } from './i_search_strategy';
|
||||
ISearchSetup,
|
||||
ISearchStart,
|
||||
TStrategyTypes,
|
||||
ISearchStrategy,
|
||||
} from './types';
|
||||
|
||||
export { getDefaultSearchParams, getTotalLoaded } from './es_search';
|
||||
|
|
|
@ -17,10 +17,14 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export const searchSetupMock = {
|
||||
registerSearchStrategyContext: jest.fn(),
|
||||
registerSearchStrategyProvider: jest.fn(),
|
||||
__LEGACY: {
|
||||
search: jest.fn(),
|
||||
},
|
||||
};
|
||||
export function createSearchSetupMock() {
|
||||
return {
|
||||
registerSearchStrategy: jest.fn(),
|
||||
};
|
||||
}
|
||||
|
||||
export function createSearchStartMock() {
|
||||
return {
|
||||
getSearchStrategy: jest.fn(),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,36 +17,26 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { httpServiceMock, httpServerMock } from '../../../../../src/core/server/mocks';
|
||||
import { CoreSetup, RequestHandlerContext } from '../../../../../src/core/server';
|
||||
import { coreMock, httpServerMock } from '../../../../../src/core/server/mocks';
|
||||
import { registerSearchRoute } from './routes';
|
||||
import { IRouter, ScopedClusterClient, RequestHandlerContext } from 'kibana/server';
|
||||
import { DataPluginStart } from '../plugin';
|
||||
import { dataPluginMock } from '../mocks';
|
||||
|
||||
describe('Search service', () => {
|
||||
let routerMock: jest.Mocked<IRouter>;
|
||||
let mockDataStart: MockedKeys<DataPluginStart>;
|
||||
let mockCoreSetup: MockedKeys<CoreSetup<object, DataPluginStart>>;
|
||||
|
||||
beforeEach(() => {
|
||||
routerMock = httpServiceMock.createRouter();
|
||||
});
|
||||
|
||||
it('registers a post route', async () => {
|
||||
registerSearchRoute(routerMock);
|
||||
expect(routerMock.post).toBeCalled();
|
||||
mockDataStart = dataPluginMock.createStartContract();
|
||||
mockCoreSetup = coreMock.createSetup({ pluginStartContract: mockDataStart });
|
||||
});
|
||||
|
||||
it('handler calls context.search.search with the given request and strategy', async () => {
|
||||
const mockSearch = jest.fn().mockResolvedValue('yay');
|
||||
const mockContext = {
|
||||
core: {
|
||||
elasticsearch: {
|
||||
legacy: {
|
||||
client: {} as ScopedClusterClient,
|
||||
},
|
||||
},
|
||||
},
|
||||
search: {
|
||||
search: mockSearch,
|
||||
},
|
||||
};
|
||||
mockDataStart.search.getSearchStrategy.mockReturnValueOnce({ search: mockSearch });
|
||||
|
||||
const mockContext = {};
|
||||
const mockBody = { params: {} };
|
||||
const mockParams = { strategy: 'foo' };
|
||||
const mockRequest = httpServerMock.createKibanaRequest({
|
||||
|
@ -55,13 +45,15 @@ describe('Search service', () => {
|
|||
});
|
||||
const mockResponse = httpServerMock.createResponseFactory();
|
||||
|
||||
registerSearchRoute(routerMock);
|
||||
const handler = routerMock.post.mock.calls[0][1];
|
||||
registerSearchRoute(mockCoreSetup);
|
||||
|
||||
const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value;
|
||||
const handler = mockRouter.post.mock.calls[0][1];
|
||||
await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse);
|
||||
|
||||
expect(mockDataStart.search.getSearchStrategy.mock.calls[0][0]).toBe(mockParams.strategy);
|
||||
expect(mockSearch).toBeCalled();
|
||||
expect(mockSearch.mock.calls[0][0]).toStrictEqual(mockBody);
|
||||
expect(mockSearch.mock.calls[0][2]).toBe(mockParams.strategy);
|
||||
expect(mockSearch.mock.calls[0][1]).toStrictEqual(mockBody);
|
||||
expect(mockResponse.ok).toBeCalled();
|
||||
expect(mockResponse.ok.mock.calls[0][0]).toEqual({ body: 'yay' });
|
||||
});
|
||||
|
@ -73,18 +65,9 @@ describe('Search service', () => {
|
|||
error: 'oops',
|
||||
},
|
||||
});
|
||||
const mockContext = {
|
||||
core: {
|
||||
elasticsearch: {
|
||||
legacy: {
|
||||
client: {} as ScopedClusterClient,
|
||||
},
|
||||
},
|
||||
},
|
||||
search: {
|
||||
search: mockSearch,
|
||||
},
|
||||
};
|
||||
mockDataStart.search.getSearchStrategy.mockReturnValueOnce({ search: mockSearch });
|
||||
|
||||
const mockContext = {};
|
||||
const mockBody = { params: {} };
|
||||
const mockParams = { strategy: 'foo' };
|
||||
const mockRequest = httpServerMock.createKibanaRequest({
|
||||
|
@ -93,13 +76,15 @@ describe('Search service', () => {
|
|||
});
|
||||
const mockResponse = httpServerMock.createResponseFactory();
|
||||
|
||||
registerSearchRoute(routerMock);
|
||||
const handler = routerMock.post.mock.calls[0][1];
|
||||
registerSearchRoute(mockCoreSetup);
|
||||
|
||||
const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value;
|
||||
const handler = mockRouter.post.mock.calls[0][1];
|
||||
await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse);
|
||||
|
||||
expect(mockDataStart.search.getSearchStrategy.mock.calls[0][0]).toBe(mockParams.strategy);
|
||||
expect(mockSearch).toBeCalled();
|
||||
expect(mockSearch.mock.calls[0][0]).toStrictEqual(mockBody);
|
||||
expect(mockSearch.mock.calls[0][2]).toBe(mockParams.strategy);
|
||||
expect(mockSearch.mock.calls[0][1]).toStrictEqual(mockBody);
|
||||
expect(mockResponse.customError).toBeCalled();
|
||||
const error: any = mockResponse.customError.mock.calls[0][0];
|
||||
expect(error.body.message).toBe('oh no');
|
||||
|
|
|
@ -18,10 +18,13 @@
|
|||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { IRouter } from '../../../../core/server';
|
||||
import { CoreSetup } from '../../../../core/server';
|
||||
import { getRequestAbortedSignal } from '../lib';
|
||||
import { DataPluginStart } from '../plugin';
|
||||
|
||||
export function registerSearchRoute(core: CoreSetup<object, DataPluginStart>): void {
|
||||
const router = core.http.createRouter();
|
||||
|
||||
export function registerSearchRoute(router: IRouter): void {
|
||||
router.post(
|
||||
{
|
||||
path: '/internal/search/{strategy}',
|
||||
|
@ -38,8 +41,11 @@ export function registerSearchRoute(router: IRouter): void {
|
|||
const { strategy } = request.params;
|
||||
const signal = getRequestAbortedSignal(request.events.aborted$);
|
||||
|
||||
const [, , selfStart] = await core.getStartServices();
|
||||
const searchStrategy = selfStart.search.getSearchStrategy(strategy);
|
||||
|
||||
try {
|
||||
const response = await context.search!.search(searchRequest, { signal }, strategy);
|
||||
const response = await searchStrategy.search(context, searchRequest, { signal });
|
||||
return res.ok({ body: response });
|
||||
} catch (err) {
|
||||
return res.customError({
|
||||
|
@ -69,8 +75,13 @@ export function registerSearchRoute(router: IRouter): void {
|
|||
},
|
||||
async (context, request, res) => {
|
||||
const { strategy, id } = request.params;
|
||||
|
||||
const [, , selfStart] = await core.getStartServices();
|
||||
const searchStrategy = selfStart.search.getSearchStrategy(strategy);
|
||||
if (!searchStrategy.cancel) return res.ok();
|
||||
|
||||
try {
|
||||
await context.search!.cancel(id, strategy);
|
||||
await searchStrategy.cancel(context, id);
|
||||
return res.ok();
|
||||
} catch (err) {
|
||||
return res.customError({
|
||||
|
|
|
@ -21,27 +21,28 @@ import { coreMock } from '../../../../core/server/mocks';
|
|||
|
||||
import { SearchService } from './search_service';
|
||||
import { CoreSetup } from '../../../../core/server';
|
||||
|
||||
const mockSearchApi = { search: jest.fn() };
|
||||
jest.mock('./create_api', () => ({
|
||||
createApi: () => mockSearchApi,
|
||||
}));
|
||||
import { DataPluginStart } from '../plugin';
|
||||
|
||||
describe('Search service', () => {
|
||||
let plugin: SearchService;
|
||||
let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
let mockCoreSetup: MockedKeys<CoreSetup<object, DataPluginStart>>;
|
||||
|
||||
beforeEach(() => {
|
||||
plugin = new SearchService(coreMock.createPluginInitializerContext({}));
|
||||
mockCoreSetup = coreMock.createSetup();
|
||||
mockSearchApi.search.mockClear();
|
||||
});
|
||||
|
||||
describe('setup()', () => {
|
||||
it('exposes proper contract', async () => {
|
||||
const setup = plugin.setup(mockCoreSetup);
|
||||
expect(setup).toHaveProperty('registerSearchStrategyContext');
|
||||
expect(setup).toHaveProperty('registerSearchStrategyProvider');
|
||||
expect(setup).toHaveProperty('registerSearchStrategy');
|
||||
});
|
||||
});
|
||||
|
||||
describe('start()', () => {
|
||||
it('exposes proper contract', async () => {
|
||||
const setup = plugin.start();
|
||||
expect(setup).toHaveProperty('getSearchStrategy');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,82 +17,52 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { Plugin, PluginInitializerContext, CoreSetup } from '../../../../core/server';
|
||||
import {
|
||||
PluginInitializerContext,
|
||||
Plugin,
|
||||
CoreSetup,
|
||||
IContextContainer,
|
||||
} from '../../../../core/server';
|
||||
import { registerSearchRoute } from './routes';
|
||||
import { ISearchSetup } from './i_search_setup';
|
||||
import { createApi } from './create_api';
|
||||
import {
|
||||
ISearchSetup,
|
||||
ISearchStart,
|
||||
TSearchStrategiesMap,
|
||||
TSearchStrategyProvider,
|
||||
TRegisterSearchStrategyProvider,
|
||||
} from './i_search_strategy';
|
||||
import { IRouteHandlerSearchContext } from './i_route_handler_search_context';
|
||||
TRegisterSearchStrategy,
|
||||
TGetSearchStrategy,
|
||||
} from './types';
|
||||
import { registerSearchRoute } from './routes';
|
||||
import { ES_SEARCH_STRATEGY, esSearchStrategyProvider } from './es_search';
|
||||
|
||||
import { searchSavedObjectType } from '../saved_objects';
|
||||
import { DataPluginStart } from '../plugin';
|
||||
|
||||
declare module 'kibana/server' {
|
||||
interface RequestHandlerContext {
|
||||
search?: IRouteHandlerSearchContext;
|
||||
}
|
||||
}
|
||||
|
||||
export class SearchService implements Plugin<ISearchSetup, void> {
|
||||
export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
||||
private searchStrategies: TSearchStrategiesMap = {};
|
||||
|
||||
private contextContainer?: IContextContainer<TSearchStrategyProvider<any>>;
|
||||
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
|
||||
public setup(core: CoreSetup): ISearchSetup {
|
||||
const router = core.http.createRouter();
|
||||
registerSearchRoute(router);
|
||||
|
||||
this.contextContainer = core.context.createContextContainer();
|
||||
|
||||
public setup(core: CoreSetup<object, DataPluginStart>): ISearchSetup {
|
||||
core.savedObjects.registerType(searchSavedObjectType);
|
||||
|
||||
core.http.registerRouteHandlerContext<'search'>('search', (context) => {
|
||||
return createApi({
|
||||
caller: context.core.elasticsearch.legacy.client.callAsCurrentUser,
|
||||
searchStrategies: this.searchStrategies,
|
||||
});
|
||||
});
|
||||
|
||||
const registerSearchStrategyProvider: TRegisterSearchStrategyProvider = (
|
||||
plugin,
|
||||
name,
|
||||
strategyProvider
|
||||
) => {
|
||||
this.searchStrategies[name] = this.contextContainer!.createHandler(plugin, strategyProvider);
|
||||
};
|
||||
|
||||
const api: ISearchSetup = {
|
||||
registerSearchStrategyContext: this.contextContainer!.registerContext,
|
||||
registerSearchStrategyProvider,
|
||||
};
|
||||
|
||||
api.registerSearchStrategyContext(this.initializerContext.opaqueId, 'core', () => core);
|
||||
api.registerSearchStrategyContext(
|
||||
this.initializerContext.opaqueId,
|
||||
'config$',
|
||||
() => this.initializerContext.config.legacy.globalConfig$
|
||||
);
|
||||
|
||||
api.registerSearchStrategyProvider(
|
||||
this.initializerContext.opaqueId,
|
||||
this.registerSearchStrategy(
|
||||
ES_SEARCH_STRATEGY,
|
||||
esSearchStrategyProvider
|
||||
esSearchStrategyProvider(this.initializerContext.config.legacy.globalConfig$)
|
||||
);
|
||||
|
||||
return api;
|
||||
registerSearchRoute(core);
|
||||
|
||||
return { registerSearchStrategy: this.registerSearchStrategy };
|
||||
}
|
||||
|
||||
public start(): ISearchStart {
|
||||
return { getSearchStrategy: this.getSearchStrategy };
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public stop() {}
|
||||
|
||||
private registerSearchStrategy: TRegisterSearchStrategy = (name, strategy) => {
|
||||
this.searchStrategies[name] = strategy;
|
||||
};
|
||||
|
||||
private getSearchStrategy: TGetSearchStrategy = (name) => {
|
||||
const strategy = this.searchStrategies[name];
|
||||
if (!strategy) {
|
||||
throw new Error(`Search strategy ${name} not found`);
|
||||
}
|
||||
return strategy;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,39 +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 { ES_SEARCH_STRATEGY } from '../../common/search/es_search';
|
||||
|
||||
/**
|
||||
* Contains all known strategy type identifiers that will be used to map to
|
||||
* request and response shapes. Plugins that wish to add their own custom search
|
||||
* strategies should extend this type via:
|
||||
*
|
||||
* const MY_STRATEGY = 'MY_STRATEGY';
|
||||
*
|
||||
* declare module 'src/plugins/search/server' {
|
||||
* export interface IRequestTypesMap {
|
||||
* [MY_STRATEGY]: IMySearchRequest;
|
||||
* }
|
||||
*
|
||||
* export interface IResponseTypesMap {
|
||||
* [MY_STRATEGY]: IMySearchResponse
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export type TStrategyTypes = typeof ES_SEARCH_STRATEGY | string;
|
111
src/plugins/data/server/search/types.ts
Normal file
111
src/plugins/data/server/search/types.ts
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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 { RequestHandlerContext } from '../../../../core/server';
|
||||
import { IKibanaSearchResponse, IKibanaSearchRequest } from '../../common/search';
|
||||
import { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from './es_search';
|
||||
|
||||
export interface ISearchSetup {
|
||||
/**
|
||||
* Extension point exposed for other plugins to register their own search
|
||||
* strategies.
|
||||
*/
|
||||
registerSearchStrategy: TRegisterSearchStrategy;
|
||||
}
|
||||
|
||||
export interface ISearchStart {
|
||||
/**
|
||||
* Get other registered search strategies. For example, if a new strategy needs to use the
|
||||
* already-registered ES search strategy, it can use this function to accomplish that.
|
||||
*/
|
||||
getSearchStrategy: TGetSearchStrategy;
|
||||
}
|
||||
|
||||
export interface ISearchOptions {
|
||||
/**
|
||||
* An `AbortSignal` that allows the caller of `search` to abort a search request.
|
||||
*/
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains all known strategy type identifiers that will be used to map to
|
||||
* request and response shapes. Plugins that wish to add their own custom search
|
||||
* strategies should extend this type via:
|
||||
*
|
||||
* const MY_STRATEGY = 'MY_STRATEGY';
|
||||
*
|
||||
* declare module 'src/plugins/search/server' {
|
||||
* export interface IRequestTypesMap {
|
||||
* [MY_STRATEGY]: IMySearchRequest;
|
||||
* }
|
||||
*
|
||||
* export interface IResponseTypesMap {
|
||||
* [MY_STRATEGY]: IMySearchResponse
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export type TStrategyTypes = typeof ES_SEARCH_STRATEGY | string;
|
||||
|
||||
/**
|
||||
* The map of search strategy IDs to the corresponding request type definitions.
|
||||
*/
|
||||
export interface IRequestTypesMap {
|
||||
[ES_SEARCH_STRATEGY]: IEsSearchRequest;
|
||||
[key: string]: IKibanaSearchRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* The map of search strategy IDs to the corresponding response type definitions.
|
||||
*/
|
||||
export interface IResponseTypesMap {
|
||||
[ES_SEARCH_STRATEGY]: IEsSearchResponse;
|
||||
[key: string]: IKibanaSearchResponse;
|
||||
}
|
||||
|
||||
export type ISearch<T extends TStrategyTypes> = (
|
||||
context: RequestHandlerContext,
|
||||
request: IRequestTypesMap[T],
|
||||
options?: ISearchOptions
|
||||
) => Promise<IResponseTypesMap[T]>;
|
||||
|
||||
export type ISearchCancel<T extends TStrategyTypes> = (
|
||||
context: RequestHandlerContext,
|
||||
id: string
|
||||
) => Promise<void>;
|
||||
|
||||
/**
|
||||
* Search strategy interface contains a search method that takes in a request and returns a promise
|
||||
* that resolves to a response.
|
||||
*/
|
||||
export interface ISearchStrategy<T extends TStrategyTypes> {
|
||||
search: ISearch<T>;
|
||||
cancel?: ISearchCancel<T>;
|
||||
}
|
||||
|
||||
export type TRegisterSearchStrategy = <T extends TStrategyTypes>(
|
||||
name: T,
|
||||
searchStrategy: ISearchStrategy<T>
|
||||
) => void;
|
||||
|
||||
export type TGetSearchStrategy = <T extends TStrategyTypes>(name: T) => ISearchStrategy<T>;
|
||||
|
||||
export type TSearchStrategiesMap = {
|
||||
[K in TStrategyTypes]?: ISearchStrategy<any>;
|
||||
};
|
|
@ -48,7 +48,6 @@ import { GetResponse } from 'elasticsearch';
|
|||
import { GetScriptParams } from 'elasticsearch';
|
||||
import { GetSourceParams } from 'elasticsearch';
|
||||
import { GetTemplateParams } from 'elasticsearch';
|
||||
import { IContextProvider as IContextProvider_2 } from 'kibana/server';
|
||||
import { IncomingHttpHeaders } from 'http';
|
||||
import { IndexDocumentParams } from 'elasticsearch';
|
||||
import { IndicesAnalyzeParams } from 'elasticsearch';
|
||||
|
@ -492,7 +491,7 @@ export class IndexPatternsFetcher {
|
|||
|
||||
// Warning: (ae-missing-release-tag) "IRequestTypesMap" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export interface IRequestTypesMap {
|
||||
// Warning: (ae-forgotten-export) The symbol "IKibanaSearchRequest" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
|
@ -507,7 +506,7 @@ export interface IRequestTypesMap {
|
|||
|
||||
// Warning: (ae-missing-release-tag) "IResponseTypesMap" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public
|
||||
export interface IResponseTypesMap {
|
||||
// Warning: (ae-forgotten-export) The symbol "IKibanaSearchResponse" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
|
@ -519,37 +518,50 @@ export interface IResponseTypesMap {
|
|||
[ES_SEARCH_STRATEGY]: IEsSearchResponse;
|
||||
}
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "TStrategyTypes" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-forgotten-export) The symbol "RequestHandlerContext" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "ISearch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type ISearch<T extends TStrategyTypes> = (request: IRequestTypesMap[T], options?: ISearchOptions) => Promise<IResponseTypesMap[T]>;
|
||||
export type ISearch<T extends TStrategyTypes> = (context: RequestHandlerContext, request: IRequestTypesMap[T], options?: ISearchOptions) => Promise<IResponseTypesMap[T]>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ISearchCancel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type ISearchCancel<T extends TStrategyTypes> = (id: string) => Promise<void>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ISearchContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface ISearchContext {
|
||||
// (undocumented)
|
||||
config$: Observable<SharedGlobalConfig>;
|
||||
// Warning: (ae-forgotten-export) The symbol "CoreSetup" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
core: CoreSetup;
|
||||
}
|
||||
export type ISearchCancel<T extends TStrategyTypes> = (context: RequestHandlerContext, id: string) => Promise<void>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ISearchOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface ISearchOptions {
|
||||
// (undocumented)
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ISearchSetup" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface ISearchSetup {
|
||||
// Warning: (ae-forgotten-export) The symbol "TRegisterSearchStrategy" needs to be exported by the entry point index.d.ts
|
||||
registerSearchStrategy: TRegisterSearchStrategy;
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ISearchStart" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface ISearchStart {
|
||||
// Warning: (ae-forgotten-export) The symbol "TGetSearchStrategy" needs to be exported by the entry point index.d.ts
|
||||
getSearchStrategy: TGetSearchStrategy;
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ISearchStrategy" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public
|
||||
export interface ISearchStrategy<T extends TStrategyTypes> {
|
||||
// (undocumented)
|
||||
cancel?: ISearchCancel<T>;
|
||||
// (undocumented)
|
||||
search: ISearch<T>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export enum KBN_FIELD_TYPES {
|
||||
// (undocumented)
|
||||
|
@ -614,21 +626,23 @@ export function parseInterval(interval: string): moment.Duration | null;
|
|||
export class Plugin implements Plugin_2<PluginSetup, PluginStart> {
|
||||
// Warning: (ae-forgotten-export) The symbol "PluginInitializerContext" needs to be exported by the entry point index.d.ts
|
||||
constructor(initializerContext: PluginInitializerContext<ConfigSchema>);
|
||||
// Warning: (ae-forgotten-export) The symbol "CoreSetup" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-forgotten-export) The symbol "DataPluginSetupDependencies" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
setup(core: CoreSetup, { usageCollection }: DataPluginSetupDependencies): {
|
||||
setup(core: CoreSetup<object, PluginStart>, { usageCollection }: DataPluginSetupDependencies): {
|
||||
search: ISearchSetup;
|
||||
fieldFormats: {
|
||||
register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number;
|
||||
};
|
||||
search: ISearchSetup;
|
||||
};
|
||||
// Warning: (ae-forgotten-export) The symbol "CoreStart" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
start(core: CoreStart): {
|
||||
search: ISearchStart;
|
||||
fieldFormats: {
|
||||
fieldFormatServiceFactory: (uiSettings: import("kibana/server").IUiSettingsClient) => Promise<import("../common").FieldFormatsRegistry>;
|
||||
fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise<import("../common").FieldFormatsRegistry>;
|
||||
};
|
||||
};
|
||||
// (undocumented)
|
||||
|
@ -658,6 +672,8 @@ export interface PluginStart {
|
|||
//
|
||||
// (undocumented)
|
||||
fieldFormats: FieldFormatsStart;
|
||||
// (undocumented)
|
||||
search: ISearchStart;
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "Query" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
|
@ -715,12 +731,10 @@ export interface TimeRange {
|
|||
to: string;
|
||||
}
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "ISearchGeneric" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-forgotten-export) The symbol "ISearchStrategy" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "TSearchStrategyProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
// Warning: (ae-missing-release-tag) "TStrategyTypes" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public
|
||||
export type TSearchStrategyProvider<T extends TStrategyTypes> = (context: ISearchContext, caller: APICaller_2, search: ISearchGeneric) => ISearchStrategy<T>;
|
||||
export type TStrategyTypes = typeof ES_SEARCH_STRATEGY | string;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "UI_SETTINGS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
|
@ -780,13 +794,12 @@ export const UI_SETTINGS: {
|
|||
// src/plugins/data/server/index.ts:103:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:131:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:131:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:184:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:185:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:186:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:187:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:188:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:191:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/plugin.ts:66:14 - (ae-forgotten-export) The symbol "ISearchSetup" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:186:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:187:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:188:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:189:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:190:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:193:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
|
|||
await supertest
|
||||
.get('/api/np-context-in-legacy')
|
||||
.expect(200)
|
||||
.expect(JSON.stringify({ contexts: ['core', 'search', 'pluginA'] }));
|
||||
.expect(JSON.stringify({ contexts: ['core', 'pluginA'] }));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -22,10 +22,9 @@ export class EnhancedDataServerPlugin implements Plugin<void, void, SetupDepende
|
|||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
|
||||
public setup(core: CoreSetup, deps: SetupDependencies) {
|
||||
deps.data.search.registerSearchStrategyProvider(
|
||||
this.initializerContext.opaqueId,
|
||||
deps.data.search.registerSearchStrategy(
|
||||
ES_SEARCH_STRATEGY,
|
||||
enhancedEsSearchStrategyProvider
|
||||
enhancedEsSearchStrategyProvider(this.initializerContext.config.legacy.globalConfig$)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { coreMock, pluginInitializerContextConfigMock } from '../../../../../src/core/server/mocks';
|
||||
import { RequestHandlerContext } from '../../../../../src/core/server';
|
||||
import { pluginInitializerContextConfigMock } from '../../../../../src/core/server/mocks';
|
||||
import { enhancedEsSearchStrategyProvider } from './es_search_strategy';
|
||||
|
||||
const mockAsyncResponse = {
|
||||
|
@ -29,25 +30,18 @@ const mockRollupResponse = {
|
|||
};
|
||||
|
||||
describe('ES search strategy', () => {
|
||||
const mockCoreSetup = coreMock.createSetup();
|
||||
const mockApiCaller = jest.fn();
|
||||
const mockSearch = jest.fn();
|
||||
const mockContext = {
|
||||
core: { elasticsearch: { legacy: { client: { callAsCurrentUser: mockApiCaller } } } },
|
||||
};
|
||||
const mockConfig$ = pluginInitializerContextConfigMock<any>({}).legacy.globalConfig$;
|
||||
|
||||
beforeEach(() => {
|
||||
mockApiCaller.mockClear();
|
||||
mockSearch.mockClear();
|
||||
});
|
||||
|
||||
it('returns a strategy with `search`', () => {
|
||||
const esSearch = enhancedEsSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
config$: mockConfig$,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
it('returns a strategy with `search`', async () => {
|
||||
const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$);
|
||||
|
||||
expect(typeof esSearch.search).toBe('function');
|
||||
});
|
||||
|
@ -56,16 +50,9 @@ describe('ES search strategy', () => {
|
|||
mockApiCaller.mockResolvedValueOnce(mockAsyncResponse);
|
||||
|
||||
const params = { index: 'logstash-*', body: { query: {} } };
|
||||
const esSearch = enhancedEsSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
config$: mockConfig$,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$);
|
||||
|
||||
await esSearch.search({ params });
|
||||
await esSearch.search((mockContext as unknown) as RequestHandlerContext, { params });
|
||||
|
||||
expect(mockApiCaller).toBeCalled();
|
||||
expect(mockApiCaller.mock.calls[0][0]).toBe('transport.request');
|
||||
|
@ -79,16 +66,9 @@ describe('ES search strategy', () => {
|
|||
mockApiCaller.mockResolvedValueOnce(mockAsyncResponse);
|
||||
|
||||
const params = { index: 'logstash-*', body: { query: {} } };
|
||||
const esSearch = enhancedEsSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
config$: mockConfig$,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$);
|
||||
|
||||
await esSearch.search({ id: 'foo', params });
|
||||
await esSearch.search((mockContext as unknown) as RequestHandlerContext, { id: 'foo', params });
|
||||
|
||||
expect(mockApiCaller).toBeCalled();
|
||||
expect(mockApiCaller.mock.calls[0][0]).toBe('transport.request');
|
||||
|
@ -102,16 +82,9 @@ describe('ES search strategy', () => {
|
|||
mockApiCaller.mockResolvedValueOnce(mockAsyncResponse);
|
||||
|
||||
const params = { index: 'foo-程', body: {} };
|
||||
const esSearch = enhancedEsSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
config$: mockConfig$,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$);
|
||||
|
||||
await esSearch.search({ params });
|
||||
await esSearch.search((mockContext as unknown) as RequestHandlerContext, { params });
|
||||
|
||||
expect(mockApiCaller).toBeCalled();
|
||||
expect(mockApiCaller.mock.calls[0][0]).toBe('transport.request');
|
||||
|
@ -124,16 +97,12 @@ describe('ES search strategy', () => {
|
|||
mockApiCaller.mockResolvedValueOnce(mockRollupResponse);
|
||||
|
||||
const params = { index: 'foo-程', body: {} };
|
||||
const esSearch = enhancedEsSearchStrategyProvider(
|
||||
{
|
||||
core: mockCoreSetup,
|
||||
config$: mockConfig$,
|
||||
},
|
||||
mockApiCaller,
|
||||
mockSearch
|
||||
);
|
||||
const esSearch = await enhancedEsSearchStrategyProvider(mockConfig$);
|
||||
|
||||
await esSearch.search({ indexType: 'rollup', params });
|
||||
await esSearch.search((mockContext as unknown) as RequestHandlerContext, {
|
||||
indexType: 'rollup',
|
||||
params,
|
||||
});
|
||||
|
||||
expect(mockApiCaller).toBeCalled();
|
||||
expect(mockApiCaller.mock.calls[0][0]).toBe('transport.request');
|
||||
|
|
|
@ -7,16 +7,16 @@
|
|||
import { first } from 'rxjs/operators';
|
||||
import { mapKeys, snakeCase } from 'lodash';
|
||||
import { SearchResponse } from 'elasticsearch';
|
||||
import { APICaller } from '../../../../../src/core/server';
|
||||
import { Observable } from 'rxjs';
|
||||
import { APICaller, SharedGlobalConfig } from '../../../../../src/core/server';
|
||||
import { ES_SEARCH_STRATEGY } from '../../../../../src/plugins/data/common';
|
||||
import {
|
||||
ISearchContext,
|
||||
TSearchStrategyProvider,
|
||||
ISearch,
|
||||
ISearchOptions,
|
||||
ISearchCancel,
|
||||
getDefaultSearchParams,
|
||||
getTotalLoaded,
|
||||
ISearchStrategy,
|
||||
} from '../../../../../src/plugins/data/server';
|
||||
import { IEnhancedEsSearchRequest } from '../../common';
|
||||
import { shimHitsTotal } from './shim_hits_total';
|
||||
|
@ -28,15 +28,16 @@ export interface AsyncSearchResponse<T> {
|
|||
response: SearchResponse<T>;
|
||||
}
|
||||
|
||||
export const enhancedEsSearchStrategyProvider: TSearchStrategyProvider<typeof ES_SEARCH_STRATEGY> = (
|
||||
context: ISearchContext,
|
||||
caller: APICaller
|
||||
) => {
|
||||
export const enhancedEsSearchStrategyProvider = (
|
||||
config$: Observable<SharedGlobalConfig>
|
||||
): ISearchStrategy<typeof ES_SEARCH_STRATEGY> => {
|
||||
const search: ISearch<typeof ES_SEARCH_STRATEGY> = async (
|
||||
context,
|
||||
request: IEnhancedEsSearchRequest,
|
||||
options
|
||||
) => {
|
||||
const config = await context.config$.pipe(first()).toPromise();
|
||||
const config = await config$.pipe(first()).toPromise();
|
||||
const caller = context.core.elasticsearch.legacy.client.callAsCurrentUser;
|
||||
const defaultParams = getDefaultSearchParams(config);
|
||||
const params = { ...defaultParams, ...request.params };
|
||||
|
||||
|
@ -45,10 +46,13 @@ export const enhancedEsSearchStrategyProvider: TSearchStrategyProvider<typeof ES
|
|||
: asyncSearch(caller, { ...request, params }, options);
|
||||
};
|
||||
|
||||
const cancel: ISearchCancel<typeof ES_SEARCH_STRATEGY> = async (id) => {
|
||||
const cancel: ISearchCancel<typeof ES_SEARCH_STRATEGY> = async (context, id) => {
|
||||
const method = 'DELETE';
|
||||
const path = encodeURI(`/_async_search/${id}`);
|
||||
await caller('transport.request', { method, path });
|
||||
await context.core.elasticsearch.legacy.client.callAsCurrentUser('transport.request', {
|
||||
method,
|
||||
path,
|
||||
});
|
||||
};
|
||||
|
||||
return { search, cancel };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue