{this.props.confirmButtonLabel
? this.props.confirmButtonLabel
- : i18n.translate(
- 'kibana-react.savedObjects.saveModal.duplicateTitleDescription.confirmSaveText',
- {
- defaultMessage: 'Confirm save',
- }
- )}
+ : i18n.translate('kibana-react.savedObjects.saveModal.saveButtonLabel', {
+ defaultMessage: 'Save',
+ })}
),
}}
@@ -315,7 +311,7 @@ export class SavedObjectSaveModal extends React.Component {
label={
}
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 8bc861e5823d0..d31f38ed8c3b3 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -860,7 +860,6 @@
"data.search.searchBar.savedQueryPopoverConfirmDeletionConfirmButtonText": "削除",
"data.search.searchBar.savedQueryPopoverConfirmDeletionTitle": "「{savedQueryName}」を削除しますか?",
"data.search.searchBar.savedQueryPopoverDeleteButtonAriaLabel": "保存されたクエリ {savedQueryName} を削除",
- "data.search.searchBar.savedQueryPopoverSaveAsNewButtonAriaLabel": "新規保存クエリとして保存",
"data.search.searchBar.savedQueryPopoverSaveAsNewButtonText": "新規保存",
"data.search.searchBar.savedQueryPopoverSaveButtonAriaLabel": "新規保存クエリを保存",
"data.search.searchBar.savedQueryPopoverSaveButtonText": "現在のクエリを保存",
@@ -2394,10 +2393,8 @@
"kbn.server.tutorials.zookeeperMetrics.nameTitle": "Zookeeper メトリック",
"kbn.server.tutorials.zookeeperMetrics.shortDescription": "Zookeeper サーバーから内部メトリックを取得します。",
"kbn.settings.advancedSettings.voiceAnnouncement.searchResultScreenReaderMessage": "{query} を検索しました。{sectionLenght, plural, one {# セクション} other {# セクション}}に{optionLenght, plural, one {# オプション} other { # オプション}}があります。",
- "kbn.table_list_view.listing.createNewItemButtonLabel": "新規 {entityName} を作成",
"kbn.table_list_view.listing.deleteButtonMessage": "{itemCount} 件の {entityName} を削除",
"kbn.table_list_view.listing.deleteConfirmModalDescription": "削除された {entityNamePlural} は復元できません。",
- "kbn.table_list_view.listing.deleteSelectedConfirmModal.title": "選択された {itemCount} 件の {entityName} を削除しますか?",
"kbn.table_list_view.listing.deleteSelectedItemsConfirmModal.cancelButtonLabel": "キャンセル",
"kbn.table_list_view.listing.deleteSelectedItemsConfirmModal.confirmButtonLabel": "削除",
"kbn.table_list_view.listing.deleteSelectedItemsConfirmModal.confirmButtonLabelDeleting": "削除中",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 8b8dd9a0c40dc..19b97b2973132 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -861,7 +861,6 @@
"data.search.searchBar.savedQueryPopoverConfirmDeletionConfirmButtonText": "删除",
"data.search.searchBar.savedQueryPopoverConfirmDeletionTitle": "删除“{savedQueryName}”?",
"data.search.searchBar.savedQueryPopoverDeleteButtonAriaLabel": "删除已保存查询 {savedQueryName}",
- "data.search.searchBar.savedQueryPopoverSaveAsNewButtonAriaLabel": "另存为新的已保存查询",
"data.search.searchBar.savedQueryPopoverSaveAsNewButtonText": "另存为新的",
"data.search.searchBar.savedQueryPopoverSaveButtonAriaLabel": "保存新的已保存查询",
"data.search.searchBar.savedQueryPopoverSaveButtonText": "保存当前查询",
@@ -2395,10 +2394,8 @@
"kbn.server.tutorials.zookeeperMetrics.nameTitle": "Zookeeper 指标",
"kbn.server.tutorials.zookeeperMetrics.shortDescription": "从 Zookeeper 服务器提取内部指标。",
"kbn.settings.advancedSettings.voiceAnnouncement.searchResultScreenReaderMessage": "您已搜索 {query}。{sectionLenght, plural, one {# 个部分} other {# 个部分}}中有 {optionLenght, plural, one {# 个选项} other {# 个选项}}",
- "kbn.table_list_view.listing.createNewItemButtonLabel": "创建新的{entityName}",
"kbn.table_list_view.listing.deleteButtonMessage": "删除 {itemCount} 个{entityName}",
"kbn.table_list_view.listing.deleteConfirmModalDescription": "您无法恢复删除的{entityNamePlural}。",
- "kbn.table_list_view.listing.deleteSelectedConfirmModal.title": "删除 {itemCount} 个选定{entityName}?",
"kbn.table_list_view.listing.deleteSelectedItemsConfirmModal.cancelButtonLabel": "取消",
"kbn.table_list_view.listing.deleteSelectedItemsConfirmModal.confirmButtonLabel": "删除",
"kbn.table_list_view.listing.deleteSelectedItemsConfirmModal.confirmButtonLabelDeleting": "正在删除",
From effa11ef711d6c61e96c7f9e091ce5d054d6c04d Mon Sep 17 00:00:00 2001
From: Liza Katz
Date: Thu, 10 Oct 2019 15:15:25 +0300
Subject: [PATCH 09/92] call isTimeRangeSelectorEnabled (#47809)
---
src/legacy/core_plugins/data/public/timefilter/timefilter.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/legacy/core_plugins/data/public/timefilter/timefilter.ts b/src/legacy/core_plugins/data/public/timefilter/timefilter.ts
index 64129ea2af5ff..70889038c0ec2 100644
--- a/src/legacy/core_plugins/data/public/timefilter/timefilter.ts
+++ b/src/legacy/core_plugins/data/public/timefilter/timefilter.ts
@@ -157,7 +157,7 @@ export class Timefilter {
}
public getActiveBounds(): TimeRangeBounds | undefined {
- if (this.isTimeRangeSelectorEnabled) {
+ if (this.isTimeRangeSelectorEnabled()) {
return this.getBounds();
}
}
From ae28c9b542eaa6647a4a14dcbe22ad1d935c165e Mon Sep 17 00:00:00 2001
From: Stacey Gammon
Date: Thu, 10 Oct 2019 08:51:28 -0400
Subject: [PATCH 10/92] Don't throw an error is panel is added, then removed,
before embeddable finishes loading (#46788)
* Remove this error being thrown as it can be expected in certain situations
* change test after change in logic
---
src/plugins/embeddable/public/lib/containers/container.ts | 5 ++---
src/plugins/embeddable/public/tests/container.test.ts | 7 +++----
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/src/plugins/embeddable/public/lib/containers/container.ts b/src/plugins/embeddable/public/lib/containers/container.ts
index f4fca4bbd8d6e..bce16747ed48e 100644
--- a/src/plugins/embeddable/public/lib/containers/container.ts
+++ b/src/plugins/embeddable/public/lib/containers/container.ts
@@ -181,11 +181,10 @@ export abstract class Container<
resolve(this.children[id] as TEmbeddable);
}
- // If a panel is removed before the embeddable was loaded there is a chance this will
- // never resolve.
+ // If we hit this, the panel was removed before the embeddable finished loading.
if (this.input.panels[id] === undefined) {
subscription.unsubscribe();
- reject(new PanelNotFoundError());
+ resolve(undefined);
}
});
});
diff --git a/src/plugins/embeddable/public/tests/container.test.ts b/src/plugins/embeddable/public/tests/container.test.ts
index c2044057786ae..3bdbcbad857d6 100644
--- a/src/plugins/embeddable/public/tests/container.test.ts
+++ b/src/plugins/embeddable/public/tests/container.test.ts
@@ -27,7 +27,6 @@ import {
} from '../lib/test_samples/embeddables/filterable_embeddable';
import { ERROR_EMBEDDABLE_TYPE } from '../lib/embeddables/error_embeddable';
import { Filter, FilterStateStore } from '@kbn/es-query';
-import { PanelNotFoundError } from '../lib/errors';
import { FilterableEmbeddableFactory } from '../lib/test_samples/embeddables/filterable_embeddable_factory';
import { CONTACT_CARD_EMBEDDABLE } from '../lib/test_samples/embeddables/contact_card/contact_card_embeddable_factory';
import { SlowContactCardEmbeddableFactory } from '../lib/test_samples/embeddables/contact_card/slow_contact_card_embeddable_factory';
@@ -753,7 +752,7 @@ test('untilEmbeddableLoaded() resolves if child is loaded in the container', asy
done();
});
-test('untilEmbeddableLoaded rejects with an error if child is subsequently removed', async done => {
+test('untilEmbeddableLoaded resolves with undefined if child is subsequently removed', async done => {
const { doStart, coreStart, uiActions } = testPlugin(
coreMock.createSetup(),
coreMock.createStart()
@@ -785,8 +784,8 @@ test('untilEmbeddableLoaded rejects with an error if child is subsequently remov
}
);
- container.untilEmbeddableLoaded('123').catch(error => {
- expect(error).toBeInstanceOf(PanelNotFoundError);
+ container.untilEmbeddableLoaded('123').then(embed => {
+ expect(embed).toBeUndefined();
done();
});
From 3cb74bd62804ba62aa1264096cf60efda477e01d Mon Sep 17 00:00:00 2001
From: Stacey Gammon
Date: Thu, 10 Oct 2019 08:52:08 -0400
Subject: [PATCH 11/92] Phase 1 of search services (#46742)
* Phase 1 of search services
* First review feedback
* Start on tests
* Add functional tests for search explorer
* Add unload and fix ts error
* Add index.test.ts files for coverage completeness
* Adding unit tests
* use internal route terminology. No reason this should be a public route, at least not yet.
* Move search service into data plugin
* App mount search context needs to be optional
* Add more unit tests for server stuff
* wip types fix
* fix types for new context container stuff
* put back all jest test coverage paths
* address review comments
* delete the two test files that just tested the instantiation of the search service
* expose search fn on StartContract... tested locally only
* update mocks to account for new startcontract
---
src/dev/jest/config.js | 2 +
.../data/common/search/es_search/index.ts | 20 +++
.../data/common/search/es_search/types.ts | 30 ++++
src/plugins/data/common/search/index.ts | 26 ++++
src/plugins/data/common/search/types.ts | 55 +++++++
src/plugins/data/public/index.ts | 3 +
src/plugins/data/public/mocks.ts | 3 +
src/plugins/data/public/plugin.ts | 8 +-
src/plugins/data/public/search/README.md | 13 ++
.../create_app_mount_context_search.test.ts | 69 +++++++++
.../search/create_app_mount_context_search.ts | 57 +++++++
.../es_search/es_search_service.test.ts | 43 ++++++
.../search/es_search/es_search_service.ts | 41 +++++
.../es_search/es_search_strategy.test.ts | 52 +++++++
.../search/es_search/es_search_strategy.ts | 37 +++++
.../public/search/es_search/index.test.ts | 25 +++
.../data/public/search/es_search/index.ts | 25 +++
src/plugins/data/public/search/i_search.ts | 59 +++++++
.../search/i_search_app_mount_context.ts | 24 +++
.../data/public/search/i_search_context.ts | 23 +++
.../data/public/search/i_search_setup.ts | 40 +++++
.../data/public/search/i_search_strategy.ts | 63 ++++++++
src/plugins/data/public/search/index.ts | 42 +++++
src/plugins/data/public/search/mocks.ts | 23 +++
.../data/public/search/search_service.test.ts | 41 +++++
.../data/public/search/search_service.ts | 126 +++++++++++++++
.../data/public/search/strategy_types.ts | 40 +++++
.../search/sync_search_strategy.test.ts | 58 +++++++
.../public/search/sync_search_strategy.ts | 56 +++++++
src/plugins/data/public/types.ts | 3 +
src/plugins/data/server/index.ts | 4 +
src/plugins/data/server/plugin.ts | 19 ++-
src/plugins/data/server/search/README.md | 13 ++
.../data/server/search/create_api.test.ts | 62 ++++++++
src/plugins/data/server/search/create_api.ts | 45 ++++++
.../server/search/es_search/elasticsearch.ts | 34 ++++
.../es_search/es_search_service.test.ts | 60 +++++++
.../search/es_search/es_search_service.ts | 42 +++++
.../es_search/es_search_strategy.test.ts | 102 ++++++++++++
.../search/es_search/es_search_strategy.ts | 53 +++++++
.../data/server/search/es_search/index.ts | 27 ++++
.../search/i_route_handler_search_context.ts | 24 +++
src/plugins/data/server/search/i_search.ts | 42 +++++
.../data/server/search/i_search_context.ts | 23 +++
.../data/server/search/i_search_setup.ts | 51 ++++++
.../data/server/search/i_search_strategy.ts | 66 ++++++++
src/plugins/data/server/search/index.ts | 29 ++++
src/plugins/data/server/search/mocks.ts | 26 ++++
src/plugins/data/server/search/routes.test.ts | 99 ++++++++++++
src/plugins/data/server/search/routes.ts | 46 ++++++
.../data/server/search/search_service.test.ts | 56 +++++++
.../data/server/search/search_service.ts | 97 ++++++++++++
.../data/server/search/strategy_types.ts | 39 +++++
test/functional/services/find.ts | 11 ++
test/functional/services/test_subjects.ts | 21 +++
test/plugin_functional/config.js | 1 +
.../plugins/demo_search/common/index.ts | 34 ++++
.../plugins/demo_search/kibana.json | 10 ++
.../plugins/demo_search/package.json | 17 ++
.../public/demo_search_strategy.ts | 70 +++++++++
.../plugins/demo_search/public/index.ts | 28 ++++
.../plugins/demo_search/public/plugin.ts | 61 ++++++++
.../plugins/demo_search/server/constants.ts | 20 +++
.../server/demo_search_strategy.ts | 36 +++++
.../plugins/demo_search/server/index.ts | 25 +++
.../plugins/demo_search/server/plugin.ts | 61 ++++++++
.../plugins/demo_search/tsconfig.json | 16 ++
.../plugins/search_explorer/kibana.json | 10 ++
.../plugins/search_explorer/package.json | 17 ++
.../search_explorer/public/application.tsx | 122 +++++++++++++++
.../search_explorer/public/demo_strategy.tsx | 134 ++++++++++++++++
.../search_explorer/public/do_search.tsx | 141 +++++++++++++++++
.../search_explorer/public/documentation.tsx | 102 ++++++++++++
.../search_explorer/public/es_strategy.tsx | 146 ++++++++++++++++++
.../search_explorer/public/guide_section.tsx | 137 ++++++++++++++++
.../plugins/search_explorer/public/index.ts | 22 +++
.../plugins/search_explorer/public/page.tsx | 51 ++++++
.../plugins/search_explorer/public/plugin.tsx | 42 +++++
.../search_explorer/public/search_api.tsx | 87 +++++++++++
.../plugins/search_explorer/tsconfig.json | 15 ++
.../test_suites/search/demo_data.ts | 36 +++++
.../test_suites/search/es_search.ts | 35 +++++
.../test_suites/search/index.ts | 51 ++++++
83 files changed, 3721 insertions(+), 4 deletions(-)
create mode 100644 src/plugins/data/common/search/es_search/index.ts
create mode 100644 src/plugins/data/common/search/es_search/types.ts
create mode 100644 src/plugins/data/common/search/index.ts
create mode 100644 src/plugins/data/common/search/types.ts
create mode 100644 src/plugins/data/public/search/README.md
create mode 100644 src/plugins/data/public/search/create_app_mount_context_search.test.ts
create mode 100644 src/plugins/data/public/search/create_app_mount_context_search.ts
create mode 100644 src/plugins/data/public/search/es_search/es_search_service.test.ts
create mode 100644 src/plugins/data/public/search/es_search/es_search_service.ts
create mode 100644 src/plugins/data/public/search/es_search/es_search_strategy.test.ts
create mode 100644 src/plugins/data/public/search/es_search/es_search_strategy.ts
create mode 100644 src/plugins/data/public/search/es_search/index.test.ts
create mode 100644 src/plugins/data/public/search/es_search/index.ts
create mode 100644 src/plugins/data/public/search/i_search.ts
create mode 100644 src/plugins/data/public/search/i_search_app_mount_context.ts
create mode 100644 src/plugins/data/public/search/i_search_context.ts
create mode 100644 src/plugins/data/public/search/i_search_setup.ts
create mode 100644 src/plugins/data/public/search/i_search_strategy.ts
create mode 100644 src/plugins/data/public/search/index.ts
create mode 100644 src/plugins/data/public/search/mocks.ts
create mode 100644 src/plugins/data/public/search/search_service.test.ts
create mode 100644 src/plugins/data/public/search/search_service.ts
create mode 100644 src/plugins/data/public/search/strategy_types.ts
create mode 100644 src/plugins/data/public/search/sync_search_strategy.test.ts
create mode 100644 src/plugins/data/public/search/sync_search_strategy.ts
create mode 100644 src/plugins/data/server/search/README.md
create mode 100644 src/plugins/data/server/search/create_api.test.ts
create mode 100644 src/plugins/data/server/search/create_api.ts
create mode 100644 src/plugins/data/server/search/es_search/elasticsearch.ts
create mode 100644 src/plugins/data/server/search/es_search/es_search_service.test.ts
create mode 100644 src/plugins/data/server/search/es_search/es_search_service.ts
create mode 100644 src/plugins/data/server/search/es_search/es_search_strategy.test.ts
create mode 100644 src/plugins/data/server/search/es_search/es_search_strategy.ts
create mode 100644 src/plugins/data/server/search/es_search/index.ts
create mode 100644 src/plugins/data/server/search/i_route_handler_search_context.ts
create mode 100644 src/plugins/data/server/search/i_search.ts
create mode 100644 src/plugins/data/server/search/i_search_context.ts
create mode 100644 src/plugins/data/server/search/i_search_setup.ts
create mode 100644 src/plugins/data/server/search/i_search_strategy.ts
create mode 100644 src/plugins/data/server/search/index.ts
create mode 100644 src/plugins/data/server/search/mocks.ts
create mode 100644 src/plugins/data/server/search/routes.test.ts
create mode 100644 src/plugins/data/server/search/routes.ts
create mode 100644 src/plugins/data/server/search/search_service.test.ts
create mode 100644 src/plugins/data/server/search/search_service.ts
create mode 100644 src/plugins/data/server/search/strategy_types.ts
create mode 100644 test/plugin_functional/plugins/demo_search/common/index.ts
create mode 100644 test/plugin_functional/plugins/demo_search/kibana.json
create mode 100644 test/plugin_functional/plugins/demo_search/package.json
create mode 100644 test/plugin_functional/plugins/demo_search/public/demo_search_strategy.ts
create mode 100644 test/plugin_functional/plugins/demo_search/public/index.ts
create mode 100644 test/plugin_functional/plugins/demo_search/public/plugin.ts
create mode 100644 test/plugin_functional/plugins/demo_search/server/constants.ts
create mode 100644 test/plugin_functional/plugins/demo_search/server/demo_search_strategy.ts
create mode 100644 test/plugin_functional/plugins/demo_search/server/index.ts
create mode 100644 test/plugin_functional/plugins/demo_search/server/plugin.ts
create mode 100644 test/plugin_functional/plugins/demo_search/tsconfig.json
create mode 100644 test/plugin_functional/plugins/search_explorer/kibana.json
create mode 100644 test/plugin_functional/plugins/search_explorer/package.json
create mode 100644 test/plugin_functional/plugins/search_explorer/public/application.tsx
create mode 100644 test/plugin_functional/plugins/search_explorer/public/demo_strategy.tsx
create mode 100644 test/plugin_functional/plugins/search_explorer/public/do_search.tsx
create mode 100644 test/plugin_functional/plugins/search_explorer/public/documentation.tsx
create mode 100644 test/plugin_functional/plugins/search_explorer/public/es_strategy.tsx
create mode 100644 test/plugin_functional/plugins/search_explorer/public/guide_section.tsx
create mode 100644 test/plugin_functional/plugins/search_explorer/public/index.ts
create mode 100644 test/plugin_functional/plugins/search_explorer/public/page.tsx
create mode 100644 test/plugin_functional/plugins/search_explorer/public/plugin.tsx
create mode 100644 test/plugin_functional/plugins/search_explorer/public/search_api.tsx
create mode 100644 test/plugin_functional/plugins/search_explorer/tsconfig.json
create mode 100644 test/plugin_functional/test_suites/search/demo_data.ts
create mode 100644 test/plugin_functional/test_suites/search/es_search.ts
create mode 100644 test/plugin_functional/test_suites/search/index.ts
diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js
index 39bd2015c3643..0c785a84bb469 100644
--- a/src/dev/jest/config.js
+++ b/src/dev/jest/config.js
@@ -39,6 +39,8 @@ export default {
'/test/functional/services/remote',
],
collectCoverageFrom: [
+ 'src/plugins/**/*.{ts,tsx}',
+ '!src/plugins/**/*.d.ts',
'packages/kbn-ui-framework/src/components/**/*.js',
'!packages/kbn-ui-framework/src/components/index.js',
'!packages/kbn-ui-framework/src/components/**/*/index.js',
diff --git a/src/plugins/data/common/search/es_search/index.ts b/src/plugins/data/common/search/es_search/index.ts
new file mode 100644
index 0000000000000..5b605224491b2
--- /dev/null
+++ b/src/plugins/data/common/search/es_search/index.ts
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+export { IEsSearchRequest, IEsSearchResponse, ES_SEARCH_STRATEGY } from './types';
diff --git a/src/plugins/data/common/search/es_search/types.ts b/src/plugins/data/common/search/es_search/types.ts
new file mode 100644
index 0000000000000..1576a6e38e36d
--- /dev/null
+++ b/src/plugins/data/common/search/es_search/types.ts
@@ -0,0 +1,30 @@
+/*
+ * 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 { SearchParams, SearchResponse } from 'elasticsearch';
+import { IKibanaSearchRequest, IKibanaSearchResponse } from '../types';
+
+export const ES_SEARCH_STRATEGY = 'es';
+
+export interface IEsSearchRequest extends IKibanaSearchRequest {
+ params: SearchParams;
+}
+
+export interface IEsSearchResponse extends IKibanaSearchResponse {
+ rawResponse: SearchResponse;
+}
diff --git a/src/plugins/data/common/search/index.ts b/src/plugins/data/common/search/index.ts
new file mode 100644
index 0000000000000..eb333c67b876d
--- /dev/null
+++ b/src/plugins/data/common/search/index.ts
@@ -0,0 +1,26 @@
+/*
+ * 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 './es_search';
+
+export { IKibanaSearchResponse, IKibanaSearchRequest } from './types';
+
+export const DEFAULT_SEARCH_STRATEGY = ES_SEARCH_STRATEGY;
+
+export { IEsSearchRequest, IEsSearchResponse, ES_SEARCH_STRATEGY } from './es_search';
diff --git a/src/plugins/data/common/search/types.ts b/src/plugins/data/common/search/types.ts
new file mode 100644
index 0000000000000..e1fe7d414756a
--- /dev/null
+++ b/src/plugins/data/common/search/types.ts
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+export interface IKibanaSearchResponse {
+ /**
+ * Some responses may contain a unique id to identify the request this response came from.
+ */
+ id?: string;
+
+ /**
+ * If relevant to the search strategy, return a percentage
+ * that represents how progress is indicated.
+ */
+ percentComplete?: number;
+
+ /**
+ * If relevant to the search strategy, return a total number
+ * that represents how progress is indicated.
+ */
+ total?: number;
+
+ /**
+ * If relevant to the search strategy, return a loaded number
+ * that represents how progress is indicated.
+ */
+ loaded?: number;
+}
+
+export interface IKibanaSearchRequest {
+ /**
+ * An id can be used to uniquely identify this request.
+ */
+ id?: string;
+
+ /**
+ * Optionally tell search strategies to output debug information.
+ */
+ debug?: boolean;
+}
diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts
index 91b94e09607ee..7e1b3801b62a4 100644
--- a/src/plugins/data/public/index.ts
+++ b/src/plugins/data/public/index.ts
@@ -31,3 +31,6 @@ export * from '../common';
export * from './autocomplete_provider';
export * from './types';
+
+export { IRequestTypesMap, IResponseTypesMap } from './search';
+export * from './search';
diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts
index b2d311912b982..5e60ca93378d9 100644
--- a/src/plugins/data/public/mocks.ts
+++ b/src/plugins/data/public/mocks.ts
@@ -17,6 +17,7 @@
* under the License.
*/
import { Plugin } from '.';
+import { searchSetupMock } from './search/mocks';
export type Setup = jest.Mocked>;
export type Start = jest.Mocked>;
@@ -30,6 +31,7 @@ const autocompleteMock: any = {
const createSetupContract = (): Setup => {
const setupContract: Setup = {
autocomplete: autocompleteMock as Setup['autocomplete'],
+ search: searchSetupMock,
};
return setupContract;
@@ -39,6 +41,7 @@ const createStartContract = (): Start => {
const startContract: Start = {
autocomplete: autocompleteMock as Start['autocomplete'],
getSuggestions: jest.fn(),
+ search: { search: jest.fn() },
};
return startContract;
};
diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts
index a3fa8005560ae..935a3c5754503 100644
--- a/src/plugins/data/public/plugin.ts
+++ b/src/plugins/data/public/plugin.ts
@@ -20,16 +20,21 @@
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public';
import { AutocompleteProviderRegister } from './autocomplete_provider';
import { DataPublicPluginSetup, DataPublicPluginStart } from './types';
+import { SearchService } from './search/search_service';
import { getSuggestionsProvider } from './suggestions_provider';
export class DataPublicPlugin implements Plugin {
private readonly autocomplete = new AutocompleteProviderRegister();
+ private readonly searchService: SearchService;
- constructor(initializerContext: PluginInitializerContext) {}
+ constructor(initializerContext: PluginInitializerContext) {
+ this.searchService = new SearchService(initializerContext);
+ }
public setup(core: CoreSetup): DataPublicPluginSetup {
return {
autocomplete: this.autocomplete,
+ search: this.searchService.setup(core),
};
}
@@ -37,6 +42,7 @@ export class DataPublicPlugin implements Plugin {
+ 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);
+ });
+});
diff --git a/src/plugins/data/public/search/create_app_mount_context_search.ts b/src/plugins/data/public/search/create_app_mount_context_search.ts
new file mode 100644
index 0000000000000..5659a9c863dc1
--- /dev/null
+++ b/src/plugins/data/public/search/create_app_mount_context_search.ts
@@ -0,0 +1,57 @@
+/*
+ * 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 = (
+ strategyName?: K
+ ): Promise> => {
+ const strategyProvider = searchStrategies[
+ strategyName ? strategyName : DEFAULT_SEARCH_STRATEGY
+ ] as TSearchStrategyProviderEnhanced | 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 => {
+ return strategy.search(request, options);
+ })
+ );
+ };
+
+ return { search };
+};
diff --git a/src/plugins/data/public/search/es_search/es_search_service.test.ts b/src/plugins/data/public/search/es_search/es_search_service.test.ts
new file mode 100644
index 0000000000000..d1069cd6815fe
--- /dev/null
+++ b/src/plugins/data/public/search/es_search/es_search_service.test.ts
@@ -0,0 +1,43 @@
+/*
+ * 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;
+ const opaqueId = Symbol();
+
+ beforeEach(() => {
+ service = new EsSearchService({ opaqueId });
+ mockCoreSetup = coreMock.createSetup();
+ });
+
+ describe('setup()', () => {
+ it('registers the ES search strategy', async () => {
+ service.setup(mockCoreSetup, {
+ search: searchSetupMock,
+ });
+ expect(searchSetupMock.registerSearchStrategyProvider).toBeCalled();
+ });
+ });
+});
diff --git a/src/plugins/data/public/search/es_search/es_search_service.ts b/src/plugins/data/public/search/es_search/es_search_service.ts
new file mode 100644
index 0000000000000..fe74292d9f8fa
--- /dev/null
+++ b/src/plugins/data/public/search/es_search/es_search_service.ts
@@ -0,0 +1,41 @@
+/*
+ * 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() {}
+}
diff --git a/src/plugins/data/public/search/es_search/es_search_strategy.test.ts b/src/plugins/data/public/search/es_search/es_search_strategy.test.ts
new file mode 100644
index 0000000000000..915a67412e519
--- /dev/null
+++ b/src/plugins/data/public/search/es_search/es_search_strategy.test.ts
@@ -0,0 +1,52 @@
+/*
+ * 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 { esSearchStrategyProvider } from './es_search_strategy';
+import { CoreSetup } from 'kibana/public';
+import { ES_SEARCH_STRATEGY } from '../../../common/search/es_search';
+
+describe('ES search strategy', () => {
+ let mockCoreSetup: MockedKeys;
+ const mockSearch = jest.fn();
+
+ beforeEach(() => {
+ mockCoreSetup = coreMock.createSetup();
+ mockSearch.mockClear();
+ });
+
+ it('returns a strategy with `search` that calls the sync search `search`', () => {
+ const request = { params: {} };
+ const options = {};
+
+ const esSearch = esSearchStrategyProvider(
+ {
+ core: mockCoreSetup,
+ },
+ mockSearch
+ );
+ esSearch.search(request, options);
+
+ expect(mockSearch.mock.calls[0][0]).toEqual({
+ ...request,
+ serverStrategy: ES_SEARCH_STRATEGY,
+ });
+ expect(mockSearch.mock.calls[0][1]).toBe(options);
+ });
+});
diff --git a/src/plugins/data/public/search/es_search/es_search_strategy.ts b/src/plugins/data/public/search/es_search/es_search_strategy.ts
new file mode 100644
index 0000000000000..643ded120799e
--- /dev/null
+++ b/src/plugins/data/public/search/es_search/es_search_strategy.ts
@@ -0,0 +1,37 @@
+/*
+ * 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 { Observable } from 'rxjs';
+import { ES_SEARCH_STRATEGY, IEsSearchResponse } from '../../../common/search';
+import { SYNC_SEARCH_STRATEGY } from '../sync_search_strategy';
+import { TSearchStrategyProvider, ISearchStrategy, ISearchGeneric, ISearchContext } from '..';
+
+export const esSearchStrategyProvider: TSearchStrategyProvider = (
+ context: ISearchContext,
+ search: ISearchGeneric
+): ISearchStrategy => {
+ return {
+ search: (request, options) =>
+ search(
+ { ...request, serverStrategy: ES_SEARCH_STRATEGY },
+ options,
+ SYNC_SEARCH_STRATEGY
+ ) as Observable,
+ };
+};
diff --git a/src/plugins/data/public/search/es_search/index.test.ts b/src/plugins/data/public/search/es_search/index.test.ts
new file mode 100644
index 0000000000000..7f7a2ed397d43
--- /dev/null
+++ b/src/plugins/data/public/search/es_search/index.test.ts
@@ -0,0 +1,25 @@
+/*
+ * 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 { esSearchService } from '.';
+
+it('es search service is instantiated', () => {
+ const esSearch = esSearchService({ opaqueId: Symbol() });
+ expect(esSearch).toBeDefined();
+});
diff --git a/src/plugins/data/public/search/es_search/index.ts b/src/plugins/data/public/search/es_search/index.ts
new file mode 100644
index 0000000000000..31952f14c63c5
--- /dev/null
+++ b/src/plugins/data/public/search/es_search/index.ts
@@ -0,0 +1,25 @@
+/*
+ * 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 = (
+ initializerContext: PluginInitializerContext
+) => new EsSearchService(initializerContext);
diff --git a/src/plugins/data/public/search/i_search.ts b/src/plugins/data/public/search/i_search.ts
new file mode 100644
index 0000000000000..0e256b960ffa3
--- /dev/null
+++ b/src/plugins/data/public/search/i_search.ts
@@ -0,0 +1,59 @@
+/*
+ * 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 { Observable } from 'rxjs';
+import { TStrategyTypes } from './strategy_types';
+import {
+ DEFAULT_SEARCH_STRATEGY,
+ IKibanaSearchRequest,
+ IKibanaSearchResponse,
+} from '../../common/search';
+import { SYNC_SEARCH_STRATEGY, ISyncSearchRequest } from './sync_search_strategy';
+import {
+ ES_SEARCH_STRATEGY,
+ IEsSearchRequest,
+ IEsSearchResponse,
+} from '../../common/search/es_search';
+
+export interface ISearchOptions {
+ signal?: AbortSignal;
+}
+
+export interface IRequestTypesMap {
+ [SYNC_SEARCH_STRATEGY]: ISyncSearchRequest;
+ [ES_SEARCH_STRATEGY]: IEsSearchRequest;
+ [key: string]: IKibanaSearchRequest;
+}
+
+export interface IResponseTypesMap {
+ [SYNC_SEARCH_STRATEGY]: IKibanaSearchResponse;
+ [ES_SEARCH_STRATEGY]: IEsSearchResponse;
+ [key: string]: IKibanaSearchResponse;
+}
+
+export type ISearchGeneric = (
+ request: IRequestTypesMap[T],
+ options: ISearchOptions,
+ strategy?: T
+) => Observable;
+
+export type ISearch = (
+ request: IRequestTypesMap[T],
+ options: ISearchOptions
+) => Observable;
diff --git a/src/plugins/data/public/search/i_search_app_mount_context.ts b/src/plugins/data/public/search/i_search_app_mount_context.ts
new file mode 100644
index 0000000000000..36cae0083ce56
--- /dev/null
+++ b/src/plugins/data/public/search/i_search_app_mount_context.ts
@@ -0,0 +1,24 @@
+/*
+ * 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 { ISearchGeneric } from './i_search';
+
+export interface ISearchAppMountContext {
+ search: ISearchGeneric;
+}
diff --git a/src/plugins/data/public/search/i_search_context.ts b/src/plugins/data/public/search/i_search_context.ts
new file mode 100644
index 0000000000000..da94988027ff6
--- /dev/null
+++ b/src/plugins/data/public/search/i_search_context.ts
@@ -0,0 +1,23 @@
+/*
+ * 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;
+}
diff --git a/src/plugins/data/public/search/i_search_setup.ts b/src/plugins/data/public/search/i_search_setup.ts
new file mode 100644
index 0000000000000..a59c62e2e0d9b
--- /dev/null
+++ b/src/plugins/data/public/search/i_search_setup.ts
@@ -0,0 +1,40 @@
+/*
+ * 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: (
+ pluginId: symbol,
+ contextName: TContextName,
+ provider: IContextProvider, TContextName>
+ ) => void;
+
+ /**
+ * Extension point exposed for other plugins to register their own search
+ * strategies.
+ */
+ registerSearchStrategyProvider: TRegisterSearchStrategyProvider;
+}
diff --git a/src/plugins/data/public/search/i_search_strategy.ts b/src/plugins/data/public/search/i_search_strategy.ts
new file mode 100644
index 0000000000000..bd67409d5054a
--- /dev/null
+++ b/src/plugins/data/public/search/i_search_strategy.ts
@@ -0,0 +1,63 @@
+/*
+ * 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 { ISearch, 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 {
+ search: ISearch;
+}
+
+/**
+ * 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 = (
+ search: ISearchGeneric
+) => Promise>;
+
+/**
+ * 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 = (
+ context: ISearchContext,
+ search: ISearchGeneric
+) => ISearchStrategy;
+
+/**
+ * Extension point exposed for other plugins to register their own search
+ * strategies.
+ */
+export type TRegisterSearchStrategyProvider = (
+ opaqueId: symbol,
+ name: T,
+ searchStrategyProvider: TSearchStrategyProvider
+) => void;
+
+export type TSearchStrategiesMap = {
+ [K in TStrategyTypes]?: TSearchStrategyProviderEnhanced;
+};
diff --git a/src/plugins/data/public/search/index.ts b/src/plugins/data/public/search/index.ts
new file mode 100644
index 0000000000000..d36202debd9b9
--- /dev/null
+++ b/src/plugins/data/public/search/index.ts
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+export { ISearchAppMountContext } from './i_search_app_mount_context';
+
+export { ISearchSetup } from './i_search_setup';
+
+export { ISearchContext } from './i_search_context';
+
+export {
+ ISearch,
+ ISearchOptions,
+ IRequestTypesMap,
+ IResponseTypesMap,
+ 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';
+
+export { IKibanaSearchResponse, IKibanaSearchRequest } from '../../common/search';
+
+export { ISearchStart } from './search_service';
diff --git a/src/plugins/data/public/search/mocks.ts b/src/plugins/data/public/search/mocks.ts
new file mode 100644
index 0000000000000..81a028007bc94
--- /dev/null
+++ b/src/plugins/data/public/search/mocks.ts
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+export const searchSetupMock = {
+ registerSearchStrategyContext: jest.fn(),
+ registerSearchStrategyProvider: jest.fn(),
+};
diff --git a/src/plugins/data/public/search/search_service.test.ts b/src/plugins/data/public/search/search_service.test.ts
new file mode 100644
index 0000000000000..8102b0e915fb7
--- /dev/null
+++ b/src/plugins/data/public/search/search_service.test.ts
@@ -0,0 +1,41 @@
+/*
+ * 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 { SearchService } from './search_service';
+import { CoreSetup } from '../../../../core/public';
+
+describe('Search service', () => {
+ let searchService: SearchService;
+ let mockCoreSetup: MockedKeys;
+ const opaqueId = Symbol();
+ beforeEach(() => {
+ searchService = new SearchService({ opaqueId });
+ mockCoreSetup = coreMock.createSetup();
+ });
+
+ describe('setup()', () => {
+ it('exposes proper contract', async () => {
+ const setup = searchService.setup(mockCoreSetup);
+ expect(setup).toHaveProperty('registerSearchStrategyContext');
+ expect(setup).toHaveProperty('registerSearchStrategyProvider');
+ });
+ });
+});
diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts
new file mode 100644
index 0000000000000..6030884c9f6b1
--- /dev/null
+++ b/src/plugins/data/public/search/search_service.ts
@@ -0,0 +1,126 @@
+/*
+ * 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,
+ CoreStart,
+ IContextContainer,
+ PluginOpaqueId,
+} 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 { SYNC_SEARCH_STRATEGY, syncSearchStrategyProvider } from './sync_search_strategy';
+import {
+ TSearchStrategyProvider,
+ TRegisterSearchStrategyProvider,
+ TSearchStrategiesMap,
+} from './i_search_strategy';
+import { TStrategyTypes } from './strategy_types';
+import { esSearchService } from './es_search';
+import { ISearchGeneric } from './i_search';
+
+/**
+ * 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;
+}
+
+/**
+ * The search plugin exposes two registration methods for other plugins:
+ * - registerSearchStrategyProvider for plugins to add their own custom
+ * search strategies
+ * - registerSearchStrategyContext for plugins to expose information
+ * and/or functionality for other search strategies to use
+ *
+ * It also comes with two search strategy implementations - SYNC_SEARCH_STRATEGY and ES_SEARCH_STRATEGY.
+ */
+export class SearchService implements Plugin {
+ /**
+ * A mapping of search strategies keyed by a unique identifier. Plugins can use this unique identifier
+ * to override certain strategy implementations.
+ */
+ private searchStrategies: TSearchStrategiesMap = {};
+
+ /**
+ * Exposes context to the search strategies.
+ */
+ private contextContainer?: IContextContainer>;
+
+ private search?: ISearchGeneric;
+
+ constructor(private initializerContext: PluginInitializerContext) {}
+
+ public setup(core: CoreSetup): ISearchSetup {
+ const search = (this.search = createAppMountSearchContext(this.searchStrategies).search);
+ core.application.registerMountContext<'search'>('search', () => {
+ return { search };
+ });
+
+ this.contextContainer = core.context.createContextContainer();
+
+ const registerSearchStrategyProvider: TRegisterSearchStrategyProvider = <
+ T extends TStrategyTypes
+ >(
+ plugin: PluginOpaqueId,
+ name: T,
+ strategyProvider: TSearchStrategyProvider
+ ) => {
+ this.searchStrategies[name] = this.contextContainer!.createHandler(plugin, strategyProvider);
+ };
+
+ const api = {
+ registerSearchStrategyContext: this.contextContainer!.registerContext,
+ registerSearchStrategyProvider,
+ };
+
+ 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) {
+ if (!this.search) {
+ throw new Error('Search should always be defined');
+ }
+ return { search: this.search };
+ }
+
+ public stop() {}
+}
diff --git a/src/plugins/data/public/search/strategy_types.ts b/src/plugins/data/public/search/strategy_types.ts
new file mode 100644
index 0000000000000..9afac9b546362
--- /dev/null
+++ b/src/plugins/data/public/search/strategy_types.ts
@@ -0,0 +1,40 @@
+/*
+ * 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';
+import { SYNC_SEARCH_STRATEGY } from './sync_search_strategy';
+
+/**
+ * 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/data/public' {
+ * export interface IRequestTypesMap {
+ * [MY_STRATEGY]: IMySearchRequest;
+ * }
+ *
+ * export interface IResponseTypesMap {
+ * [MY_STRATEGY]: IMySearchResponse
+ * }
+ * }
+ */
+export type TStrategyTypes = typeof SYNC_SEARCH_STRATEGY | typeof ES_SEARCH_STRATEGY | string;
diff --git a/src/plugins/data/public/search/sync_search_strategy.test.ts b/src/plugins/data/public/search/sync_search_strategy.test.ts
new file mode 100644
index 0000000000000..2737a4033a015
--- /dev/null
+++ b/src/plugins/data/public/search/sync_search_strategy.test.ts
@@ -0,0 +1,58 @@
+/*
+ * 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 { SYNC_SEARCH_STRATEGY, syncSearchStrategyProvider } from './sync_search_strategy';
+import { CoreSetup } from '../../../../core/public';
+
+describe('Sync search strategy', () => {
+ let mockCoreSetup: MockedKeys;
+ const mockSearch = jest.fn();
+
+ beforeEach(() => {
+ mockCoreSetup = coreMock.createSetup();
+ });
+
+ it('returns a strategy with `search` that calls the backend API', () => {
+ mockCoreSetup.http.fetch.mockImplementationOnce(() => Promise.resolve());
+
+ const syncSearch = syncSearchStrategyProvider(
+ {
+ core: mockCoreSetup,
+ },
+ mockSearch
+ );
+ syncSearch.search(
+ {
+ serverStrategy: SYNC_SEARCH_STRATEGY,
+ },
+ {}
+ );
+ expect(mockCoreSetup.http.fetch.mock.calls[0][0]).toBe(
+ `/internal/search/${SYNC_SEARCH_STRATEGY}`
+ );
+ expect(mockCoreSetup.http.fetch.mock.calls[0][1]).toEqual({
+ body: JSON.stringify({
+ serverStrategy: 'SYNC_SEARCH_STRATEGY',
+ }),
+ method: 'POST',
+ signal: undefined,
+ });
+ });
+});
diff --git a/src/plugins/data/public/search/sync_search_strategy.ts b/src/plugins/data/public/search/sync_search_strategy.ts
new file mode 100644
index 0000000000000..c412bbb3b104a
--- /dev/null
+++ b/src/plugins/data/public/search/sync_search_strategy.ts
@@ -0,0 +1,56 @@
+/*
+ * 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 { 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';
+
+export const SYNC_SEARCH_STRATEGY = 'SYNC_SEARCH_STRATEGY';
+
+export interface ISyncSearchRequest extends IKibanaSearchRequest {
+ serverStrategy: string;
+}
+
+export const syncSearchStrategyProvider: TSearchStrategyProvider = (
+ context: ISearchContext
+) => {
+ const search: ISearch = (
+ request: ISyncSearchRequest,
+ options: ISearchOptions
+ ) => {
+ const response: Promise = context.core.http.fetch(
+ `/internal/search/${request.serverStrategy}`,
+ {
+ method: 'POST',
+ body: JSON.stringify(request),
+ signal: options.signal,
+ }
+ );
+
+ return from(response);
+ };
+
+ const strategy: ISearchStrategy = {
+ search,
+ };
+
+ return strategy;
+};
diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts
index 70406b4dc0c0a..5f94734fef083 100644
--- a/src/plugins/data/public/types.ts
+++ b/src/plugins/data/public/types.ts
@@ -20,14 +20,17 @@
export * from './autocomplete_provider/types';
import { AutocompletePublicPluginSetup, AutocompletePublicPluginStart } from '.';
+import { ISearchSetup, ISearchStart } from './search';
import { IGetSuggestions } from './suggestions_provider/types';
export interface DataPublicPluginSetup {
autocomplete: AutocompletePublicPluginSetup;
+ search: ISearchSetup;
}
export interface DataPublicPluginStart {
autocomplete: AutocompletePublicPluginStart;
getSuggestions: IGetSuggestions;
+ search: ISearchStart;
}
export { IGetSuggestions } from './suggestions_provider/types';
diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts
index 60734f25b46a3..df933167cee25 100644
--- a/src/plugins/data/server/index.ts
+++ b/src/plugins/data/server/index.ts
@@ -25,3 +25,7 @@ export function plugin(initializerContext: PluginInitializerContext) {
}
export { DataServerPlugin as Plugin };
+
+export * from './search';
+
+export { IRequestTypesMap, IResponseTypesMap } from './search';
diff --git a/src/plugins/data/server/plugin.ts b/src/plugins/data/server/plugin.ts
index 3aa04c7a5be7a..9cf08b0702e9e 100644
--- a/src/plugins/data/server/plugin.ts
+++ b/src/plugins/data/server/plugin.ts
@@ -18,10 +18,23 @@
*/
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/server';
+import { ISearchSetup } from './search';
+import { SearchService } from './search/search_service';
-export class DataServerPlugin implements Plugin {
- constructor(initializerContext: PluginInitializerContext) {}
- public setup(core: CoreSetup) {}
+export interface DataPluginSetup {
+ search: ISearchSetup;
+}
+
+export class DataServerPlugin implements Plugin {
+ private readonly searchService: SearchService;
+ constructor(initializerContext: PluginInitializerContext) {
+ this.searchService = new SearchService(initializerContext);
+ }
+ public setup(core: CoreSetup) {
+ return {
+ search: this.searchService.setup(core),
+ };
+ }
public start(core: CoreStart) {}
public stop() {}
}
diff --git a/src/plugins/data/server/search/README.md b/src/plugins/data/server/search/README.md
new file mode 100644
index 0000000000000..33e6d9ab0bd1a
--- /dev/null
+++ b/src/plugins/data/server/search/README.md
@@ -0,0 +1,13 @@
+# search
+
+The `search` plugin provides the ability to register search strategies that take in a request
+object, and return a response object, of a given shape.
+
+Both client side search strategies can be registered, as well as server side search strategies.
+
+The `search` plugin includes two one concrete client side implementations -
+ `SYNC_SEARCH_STRATEGY` and `ES_SEARCH_STRATEGY` which uses `SYNC_SEARCH_STRATEGY`. There is also one
+ default server side search strategy, `ES_SEARCH_STRATEGY`.
+
+ Includes the `esSearch` plugin in order to search for data from Elasticsearch using Elasticsearch
+DSL.
diff --git a/src/plugins/data/server/search/create_api.test.ts b/src/plugins/data/server/search/create_api.test.ts
new file mode 100644
index 0000000000000..32570a05031f6
--- /dev/null
+++ b/src/plugins/data/server/search/create_api.test.ts
@@ -0,0 +1,62 @@
+/*
+ * 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';
+
+// let mockCoreSetup: MockedKeys;
+
+const mockDefaultSearch = jest.fn(() => Promise.resolve({ percentComplete: 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"`
+ );
+ });
+});
diff --git a/src/plugins/data/server/search/create_api.ts b/src/plugins/data/server/search/create_api.ts
new file mode 100644
index 0000000000000..4c13dd9e1137c
--- /dev/null
+++ b/src/plugins/data/server/search/create_api.ts
@@ -0,0 +1,45 @@
+/*
+ * 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, strategyName) => {
+ const name = strategyName ? 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);
+ },
+ };
+ return api;
+}
diff --git a/src/plugins/data/server/search/es_search/elasticsearch.ts b/src/plugins/data/server/search/es_search/elasticsearch.ts
new file mode 100644
index 0000000000000..6c3aa771328a8
--- /dev/null
+++ b/src/plugins/data/server/search/es_search/elasticsearch.ts
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+export interface StringMap {
+ [key: string]: T;
+}
+
+export type IndexAsString
-
+ >
-
+ >
@@ -156,7 +159,15 @@
- {{n.icon.code}}
+ {{n.icon.code}}{{n.label}} (+{{n.numChildren}})
diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js
index f267eb178f798..9bd664d3d21fa 100644
--- a/x-pack/legacy/plugins/graph/public/app.js
+++ b/x-pack/legacy/plugins/graph/public/app.js
@@ -9,6 +9,7 @@ import { i18n } from '@kbn/i18n';
import 'ace';
import React from 'react';
import { Provider } from 'react-redux';
+import { isColorDark, hexToRgb } from '@elastic/eui';
// import the uiExports that we want to "use"
import 'uiExports/fieldFormats';
@@ -98,14 +99,13 @@ app.directive('graphApp', function (reactDirective) {
['pluginDataStart', { watchDepth: 'reference' }],
['store', { watchDepth: 'reference' }],
['reduxStore', { watchDepth: 'reference' }],
- ]);
+ ], { restrict: 'A' });
});
app.directive('graphVisualization', function (reactDirective) {
- return reactDirective(GraphVisualization);
+ return reactDirective(GraphVisualization, undefined, { restrict: 'A' });
});
-
if (uiRoutes.enable) {
uiRoutes.enable();
}
@@ -324,6 +324,7 @@ app.controller('graphuiPlugin', function (
const allSavingDisabled = chrome.getInjected('graphSavePolicy') === 'none';
$scope.spymode = 'request';
$scope.colors = colorChoices;
+ $scope.isColorDark = (color) => isColorDark(...hexToRgb(color));
$scope.nodeClick = function (n, $event) {
//Selection logic - shift key+click helps selects multiple nodes
diff --git a/x-pack/legacy/plugins/graph/public/components/app.tsx b/x-pack/legacy/plugins/graph/public/components/app.tsx
index 5d0bb7758dd0d..fe9a3bdd1f6e2 100644
--- a/x-pack/legacy/plugins/graph/public/components/app.tsx
+++ b/x-pack/legacy/plugins/graph/public/components/app.tsx
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+import { EuiSpacer } from '@elastic/eui';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { Provider } from 'react-redux';
@@ -45,14 +45,9 @@ export function GraphApp(props: GraphAppProps) {
<>