From f998174898eb68f8fe3996dc7186079c336a0e34 Mon Sep 17 00:00:00 2001 From: Patrick Mueller Date: Sun, 16 Feb 2020 17:55:52 -0500 Subject: [PATCH 01/21] [eventLog] get kibana.index name from config instead of hard-coding it (#57607) fixes https://github.com/elastic/kibana/issues/55629 --- x-pack/plugins/event_log/server/plugin.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/event_log/server/plugin.ts b/x-pack/plugins/event_log/server/plugin.ts index e32d4ff6f7acc..653e753446bb1 100644 --- a/x-pack/plugins/event_log/server/plugin.ts +++ b/x-pack/plugins/event_log/server/plugin.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; import { CoreSetup, @@ -12,6 +13,7 @@ import { Plugin as CorePlugin, PluginInitializerContext, ClusterClient, + SharedGlobalConfig, } from 'src/core/server'; import { IEventLogConfig, IEventLogService, IEventLogger, IEventLogConfig$ } from './types'; @@ -20,9 +22,6 @@ import { createEsContext, EsContext } from './es'; export type PluginClusterClient = Pick; -// TODO - figure out how to get ${kibana.index} for `.kibana` -const KIBANA_INDEX = '.kibana'; - const PROVIDER = 'event_log'; const ACTIONS = { starting: 'starting', @@ -35,13 +34,18 @@ export class Plugin implements CorePlugin { private eventLogService?: IEventLogService; private esContext?: EsContext; private eventLogger?: IEventLogger; + private globalConfig$: Observable; constructor(private readonly context: PluginInitializerContext) { this.systemLogger = this.context.logger.get(); this.config$ = this.context.config.create(); + this.globalConfig$ = this.context.config.legacy.globalConfig$; } async setup(core: CoreSetup): Promise { + const globalConfig = await this.globalConfig$.pipe(first()).toPromise(); + const kibanaIndex = globalConfig.kibana.index; + this.systemLogger.debug('setting up plugin'); const config = await this.config$.pipe(first()).toPromise(); @@ -49,7 +53,7 @@ export class Plugin implements CorePlugin { this.esContext = createEsContext({ logger: this.systemLogger, // TODO: get index prefix from config.get(kibana.index) - indexNameRoot: KIBANA_INDEX, + indexNameRoot: kibanaIndex, clusterClient: core.elasticsearch.adminClient, }); From 5d3797ee0ba75faa120e1093ffe5db24f2d69f19 Mon Sep 17 00:00:00 2001 From: Patrick Mueller Date: Sun, 16 Feb 2020 20:10:35 -0500 Subject: [PATCH 02/21] change id of x-pack event_log plugin to eventLog (#57612) change id of x-pack event_log plugin to eventLog --- x-pack/plugins/actions/kibana.json | 2 +- x-pack/plugins/actions/server/plugin.test.ts | 4 ++-- x-pack/plugins/actions/server/plugin.ts | 6 +++--- x-pack/plugins/event_log/README.md | 16 ++++++++-------- x-pack/plugins/event_log/kibana.json | 4 ++-- x-pack/plugins/event_log/server/plugin.ts | 7 ++++--- .../alerting_api_integration/common/config.ts | 2 +- .../common/config.ts | 2 +- 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/actions/kibana.json b/x-pack/plugins/actions/kibana.json index ff7f22af6261d..0c40dec46a6ee 100644 --- a/x-pack/plugins/actions/kibana.json +++ b/x-pack/plugins/actions/kibana.json @@ -4,7 +4,7 @@ "version": "8.0.0", "kibanaVersion": "kibana", "configPath": ["xpack", "actions"], - "requiredPlugins": ["licensing", "taskManager", "encryptedSavedObjects", "event_log"], + "requiredPlugins": ["licensing", "taskManager", "encryptedSavedObjects", "eventLog"], "optionalPlugins": ["spaces"], "ui": false } diff --git a/x-pack/plugins/actions/server/plugin.test.ts b/x-pack/plugins/actions/server/plugin.test.ts index ba6fbcd32daee..91944dfa8f3ad 100644 --- a/x-pack/plugins/actions/server/plugin.test.ts +++ b/x-pack/plugins/actions/server/plugin.test.ts @@ -27,7 +27,7 @@ describe('Actions Plugin', () => { taskManager: taskManagerMock.createSetup(), encryptedSavedObjects: encryptedSavedObjectsMock.createSetup(), licensing: licensingMock.createSetup(), - event_log: eventLogMock.createSetup(), + eventLog: eventLogMock.createSetup(), }; }); @@ -107,7 +107,7 @@ describe('Actions Plugin', () => { taskManager: taskManagerMock.createSetup(), encryptedSavedObjects: encryptedSavedObjectsMock.createSetup(), licensing: licensingMock.createSetup(), - event_log: eventLogMock.createSetup(), + eventLog: eventLogMock.createSetup(), }; pluginsStart = { taskManager: taskManagerMock.createStart(), diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index 1714666882b05..b0555921f395f 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -70,7 +70,7 @@ export interface ActionsPluginsSetup { encryptedSavedObjects: EncryptedSavedObjectsPluginSetup; licensing: LicensingPluginSetup; spaces?: SpacesPluginSetup; - event_log: IEventLogService; + eventLog: IEventLogService; } export interface ActionsPluginsStart { encryptedSavedObjects: EncryptedSavedObjectsPluginStart; @@ -132,8 +132,8 @@ export class ActionsPlugin implements Plugin, Plugi attributesToEncrypt: new Set(['apiKey']), }); - plugins.event_log.registerProviderActions(EVENT_LOG_PROVIDER, Object.values(EVENT_LOG_ACTIONS)); - this.eventLogger = plugins.event_log.getLogger({ + plugins.eventLog.registerProviderActions(EVENT_LOG_PROVIDER, Object.values(EVENT_LOG_ACTIONS)); + this.eventLogger = plugins.eventLog.getLogger({ event: { provider: EVENT_LOG_PROVIDER }, }); diff --git a/x-pack/plugins/event_log/README.md b/x-pack/plugins/event_log/README.md index d2d67ffc27d94..027bbc694801f 100644 --- a/x-pack/plugins/event_log/README.md +++ b/x-pack/plugins/event_log/README.md @@ -9,14 +9,14 @@ and actions. ## Basic Usage - Logging Events -Follow these steps to use `event_log` in your plugin: +Follow these steps to use `eventLog` in your plugin: -1. Declare `event_log` as a dependency in `kibana.json`: +1. Declare `eventLog` as a dependency in `kibana.json`: ```json { ... - "requiredPlugins": ["event_log"], + "requiredPlugins": ["eventLog"], ... } ``` @@ -28,13 +28,13 @@ API provided in the `setup` stage: ... import { IEventLogger, IEventLogService } from '../../event_log/server'; interface PluginSetupDependencies { - event_log: IEventLogService; + eventLog: IEventLogService; } ... -public setup(core: CoreSetup, { event_log }: PluginSetupDependencies) { +public setup(core: CoreSetup, { eventLog }: PluginSetupDependencies) { ... - event_log.registerProviderActions('my-plugin', ['action-1, action-2']); - const eventLogger: IEventLogger = event_log.getLogger({ event: { provider: 'my-plugin' } }); + eventLog.registerProviderActions('my-plugin', ['action-1, action-2']); + const eventLogger: IEventLogger = eventLog.getLogger({ event: { provider: 'my-plugin' } }); ... } ... @@ -73,7 +73,7 @@ a new elasticsearch index referred to as the "event log". Example events are actions firing, alerts running their scheduled functions, alerts scheduling actions to run, etc. -This functionality will be provided in a new NP plugin `event_log`, and will +This functionality will be provided in a new NP plugin `eventLog`, and will provide server-side plugin APIs to write to the event log, and run limited queries against it. For now, access via HTTP will not be available, due to security concerns and lack of use cases. diff --git a/x-pack/plugins/event_log/kibana.json b/x-pack/plugins/event_log/kibana.json index 52b68deeffce5..7231d967b4c8d 100644 --- a/x-pack/plugins/event_log/kibana.json +++ b/x-pack/plugins/event_log/kibana.json @@ -1,8 +1,8 @@ { - "id": "event_log", + "id": "eventLog", "version": "0.0.1", "kibanaVersion": "kibana", - "configPath": ["xpack", "event_log"], + "configPath": ["xpack", "eventLog"], "server": true, "ui": false } diff --git a/x-pack/plugins/event_log/server/plugin.ts b/x-pack/plugins/event_log/server/plugin.ts index 653e753446bb1..fdb08b2d090a6 100644 --- a/x-pack/plugins/event_log/server/plugin.ts +++ b/x-pack/plugins/event_log/server/plugin.ts @@ -22,7 +22,8 @@ import { createEsContext, EsContext } from './es'; export type PluginClusterClient = Pick; -const PROVIDER = 'event_log'; +const PROVIDER = 'eventLog'; + const ACTIONS = { starting: 'starting', stopping: 'stopping', @@ -88,7 +89,7 @@ export class Plugin implements CorePlugin { // will log the event after initialization this.eventLogger.logEvent({ event: { action: ACTIONS.starting }, - message: 'event_log starting', + message: 'eventLog starting', }); } @@ -101,7 +102,7 @@ export class Plugin implements CorePlugin { // when Kibana is actuaelly stopping, as it's written asynchronously this.eventLogger.logEvent({ event: { action: ACTIONS.stopping }, - message: 'event_log stopping', + message: 'eventLog stopping', }); } } diff --git a/x-pack/test/alerting_api_integration/common/config.ts b/x-pack/test/alerting_api_integration/common/config.ts index d23bd2ac4646d..eb03aafc03d08 100644 --- a/x-pack/test/alerting_api_integration/common/config.ts +++ b/x-pack/test/alerting_api_integration/common/config.ts @@ -75,7 +75,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) ])}`, `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, '--xpack.alerting.enabled=true', - '--xpack.event_log.logEntries=true', + '--xpack.eventLog.logEntries=true', ...disabledPlugins.map(key => `--xpack.${key}.enabled=false`), `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'alerts')}`, `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'actions')}`, diff --git a/x-pack/test/detection_engine_api_integration/common/config.ts b/x-pack/test/detection_engine_api_integration/common/config.ts index bf8e6982b545d..d2bfeeb6433d3 100644 --- a/x-pack/test/detection_engine_api_integration/common/config.ts +++ b/x-pack/test/detection_engine_api_integration/common/config.ts @@ -74,7 +74,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) ])}`, `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, '--xpack.alerting.enabled=true', - '--xpack.event_log.logEntries=true', + '--xpack.eventLog.logEntries=true', ...disabledPlugins.map(key => `--xpack.${key}.enabled=false`), `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'alerts')}`, `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'actions')}`, From 8e17fdabd4954ee49ab6d2e327351cb20abc6e77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Mon, 17 Feb 2020 14:22:07 +0530 Subject: [PATCH 03/21] [Index management] Client-side NP ready (#57295) --- src/plugins/management/public/index.ts | 1 + src/plugins/management/public/types.ts | 2 +- .../components/detail_panel/detail_panel.js | 2 +- .../components/detail_panel/detail_panel.js | 2 +- .../public/extend_index_management/index.js | 4 +- .../__jest__/extend_index_management.test.js | 5 + .../components/policy_table/policy_table.js | 2 +- .../np_ready/extend_index_management/index.js | 28 +- .../helpers/home.helpers.ts | 9 +- .../helpers/setup_environment.ts | 39 --- .../helpers/setup_environment.tsx | 56 ++++ .../helpers/template_clone.helpers.ts | 5 +- .../helpers/template_create.helpers.ts | 8 +- .../helpers/template_edit.helpers.ts | 5 +- .../__jest__/components/index_table.test.js | 49 ++- .../__jest__/lib/flatten_object.test.js | 2 +- .../index_management/public/app/index.tsx | 36 -- .../index_list/detail_panel/detail_panel.js | 164 --------- .../public/app/services/ui_metric.ts | 25 -- .../public/app/store/reducers/detail_panel.js | 89 ----- .../public/{app => application}/app.tsx | 4 +- .../public/application/app_context.tsx | 52 +++ .../{app => application}/components/index.ts | 0 .../client_integration/helpers/index.ts | 0 .../helpers/mappings_editor.helpers.ts | 0 .../mappings_editor.test.tsx | 0 .../components/mappings_editor/_index.scss | 0 .../mappings_editor/components/_index.scss | 0 .../mappings_editor/components/code_block.tsx | 0 .../configuration_form/configuration_form.tsx | 0 .../configuration_form_schema.tsx | 0 .../dynamic_mapping_section.tsx | 0 .../dynamic_mapping_section/index.ts | 0 .../components/configuration_form/index.ts | 0 .../meta_field_section/index.ts | 0 .../meta_field_section/meta_field_section.tsx | 0 .../configuration_form/routing_section.tsx | 0 .../source_field_section/index.ts | 0 .../source_field_section.tsx | 0 .../components/document_fields/_index.scss | 0 .../document_fields/document_fields.tsx | 0 .../document_fields_header.tsx | 0 .../editor_toggle_controls.tsx | 0 .../field_parameters/analyzer_parameter.tsx | 0 .../analyzer_parameter_selects.tsx | 0 .../field_parameters/analyzers_parameter.tsx | 0 .../field_parameters/boost_parameter.tsx | 0 .../coerce_number_parameter.tsx | 0 .../coerce_shape_parameter.tsx | 0 .../field_parameters/copy_to_parameter.tsx | 0 .../field_parameters/doc_values_parameter.tsx | 0 .../field_parameters/dynamic_parameter.tsx | 0 .../eager_global_ordinals_parameter.tsx | 0 .../field_parameters/enabled_parameter.tsx | 0 .../fielddata_frequency_filter_absolute.tsx | 0 .../fielddata_frequency_filter_percentage.tsx | 0 .../field_parameters/fielddata_parameter.tsx | 0 .../field_parameters/format_parameter.tsx | 0 .../field_parameters/ignore_malformed.tsx | 0 .../ignore_z_value_parameter.tsx | 0 .../document_fields/field_parameters/index.ts | 0 .../field_parameters/index_parameter.tsx | 0 .../field_parameters/locale_parameter.tsx | 0 .../max_shingle_size_parameter.tsx | 0 .../field_parameters/name_parameter.tsx | 0 .../field_parameters/norms_parameter.tsx | 0 .../field_parameters/null_value_parameter.tsx | 0 .../orientation_parameter.tsx | 0 .../field_parameters/path_parameter.tsx | 0 .../field_parameters/relations_parameter.tsx | 0 .../field_parameters/similarity_parameter.tsx | 0 .../split_queries_on_whitespace_parameter.tsx | 0 .../field_parameters/store_parameter.tsx | 0 .../term_vector_parameter.tsx | 0 .../field_parameters/type_parameter.tsx | 0 .../fields/_field_list_item.scss | 0 .../document_fields/fields/_index.scss | 0 .../fields/create_field/create_field.tsx | 0 .../fields/create_field/index.ts | 0 .../required_parameters_forms/alias_type.tsx | 0 .../dense_vector_type.tsx | 0 .../required_parameters_forms/index.ts | 0 .../scaled_float_type.tsx | 0 .../token_count_type.tsx | 0 .../fields/delete_field_provider.tsx | 0 .../edit_field/_edit_field_form_row.scss | 0 .../fields/edit_field/_index.scss | 0 .../advanced_parameters_section.tsx | 0 .../edit_field/basic_parameters_section.tsx | 0 .../fields/edit_field/edit_field.tsx | 0 .../edit_field/edit_field_container.tsx | 0 .../fields/edit_field/edit_field_form_row.tsx | 0 .../edit_field/edit_field_header_form.tsx | 0 .../edit_field/field_description_section.tsx | 0 .../fields/edit_field/index.ts | 0 .../edit_field/update_field_provider.tsx | 0 .../fields/field_types/alias_type.tsx | 0 .../fields/field_types/binary_type.tsx | 0 .../fields/field_types/boolean_type.tsx | 0 .../fields/field_types/completion_type.tsx | 0 .../fields/field_types/date_type.tsx | 0 .../fields/field_types/dense_vector_type.tsx | 0 .../fields/field_types/flattened_type.tsx | 0 .../fields/field_types/geo_point_type.tsx | 0 .../fields/field_types/geo_shape_type.tsx | 0 .../fields/field_types/index.ts | 0 .../fields/field_types/ip_type.tsx | 0 .../fields/field_types/join_type.tsx | 0 .../fields/field_types/keyword_type.tsx | 0 .../fields/field_types/nested_type.tsx | 0 .../fields/field_types/numeric_type.tsx | 0 .../fields/field_types/object_type.tsx | 0 .../fields/field_types/range_type.tsx | 0 .../fields/field_types/search_as_you_type.tsx | 0 .../fields/field_types/shape_type.tsx | 0 .../fields/field_types/text_type.tsx | 0 .../fields/field_types/token_count_type.tsx | 0 .../document_fields/fields/fields_list.tsx | 0 .../fields/fields_list_item.tsx | 0 .../fields/fields_list_item_container.tsx | 0 .../document_fields/fields/index.ts | 0 .../modal_confirmation_delete_fields.tsx | 0 .../document_fields/fields_json_editor.tsx | 0 .../document_fields/fields_tree_editor.tsx | 0 .../components/document_fields/index.ts | 0 .../document_fields/search_fields/index.ts | 0 .../search_fields/search_result.tsx | 0 .../search_fields/search_result_item.tsx | 0 .../components/fields_tree.tsx | 0 .../mappings_editor/components/index.ts | 0 .../components/load_mappings/index.ts | 0 .../load_mappings/load_from_json_button.tsx | 0 .../load_mappings_provider.test.tsx | 0 .../load_mappings/load_mappings_provider.tsx | 0 .../components/multiple_mappings_warning.tsx | 0 .../components/templates_form/index.ts | 0 .../templates_form/templates_form.tsx | 0 .../templates_form/templates_form_schema.ts | 0 .../mappings_editor/components/tree/index.ts | 0 .../mappings_editor/components/tree/tree.tsx | 0 .../components/tree/tree_item.tsx | 0 .../constants/data_types_definition.tsx | 0 .../constants/default_values.ts | 0 .../constants/field_options.tsx | 0 .../constants/field_options_i18n.ts | 0 .../mappings_editor/constants/index.ts | 0 .../constants/mappings_editor.ts | 0 .../constants/parameters_definition.tsx | 0 .../components/mappings_editor/index.ts | 0 .../index_settings_context.tsx | 0 .../mappings_editor/lib/error_reporter.ts | 0 .../lib/extract_mappings_definition.test.ts | 0 .../lib/extract_mappings_definition.ts | 0 .../components/mappings_editor/lib/index.ts | 0 .../lib/mappings_validator.test.ts | 0 .../mappings_editor/lib/mappings_validator.ts | 0 .../mappings_editor/lib/search_fields.test.ts | 0 .../mappings_editor/lib/search_fields.tsx | 0 .../mappings_editor/lib/serializers.ts | 0 .../mappings_editor/lib/utils.test.ts | 0 .../components/mappings_editor/lib/utils.ts | 0 .../mappings_editor/lib/validators.ts | 0 .../mappings_editor/mappings_editor.tsx | 0 .../mappings_editor/mappings_state.tsx | 0 .../components/mappings_editor/reducer.ts | 0 .../mappings_editor/shared_imports.ts | 0 .../components/mappings_editor/types.ts | 0 .../components/no_match/index.ts | 0 .../components/no_match/no_match.tsx | 0 .../components/page_error/index.ts | 0 .../page_error/page_error_forbidden.tsx | 0 .../components/section_error.tsx | 0 .../components/section_loading.tsx | 0 .../components/template_delete_modal.tsx | 0 .../components/template_form/index.ts | 0 .../components/template_form/steps/index.ts | 0 .../template_form/steps/step_aliases.tsx | 0 .../template_form/steps/step_logistics.tsx | 0 .../template_form/steps/step_mappings.tsx | 0 .../template_form/steps/step_review.tsx | 0 .../template_form/steps/step_settings.tsx | 0 .../template_form/steps/use_json_step.ts | 0 .../template_form/template_form.tsx | 0 .../template_form/template_form_schemas.tsx | 0 .../template_form/template_steps.tsx | 0 .../components/template_form/types.ts | 0 .../constants/detail_panel_tabs.ts | 0 .../{app => application}/constants/index.ts | 0 .../constants/refresh_intervals.ts | 0 .../public/application/index.tsx | 45 +++ .../public/{app => application}/lib/ace.js | 0 .../{app => application}/lib/edit_settings.js | 0 .../lib/flatten_object.js | 0 .../lib/flatten_panel_tree.js | 0 .../lib/index_status_labels.js | 0 .../lib/manage_angular_lifecycle.ts | 0 .../{app => application}/lib/render_badges.js | 6 +- .../sections/home/home.tsx | 0 .../sections/home/index.ts | 0 .../detail_panel/detail_panel.container.js | 0 .../index_list/detail_panel/detail_panel.js | 167 ++++++++++ .../edit_settings_json.container.js | 0 .../edit_settings_json/edit_settings_json.js | 0 .../detail_panel/edit_settings_json/index.js | 0 .../home/index_list/detail_panel/index.js | 0 .../detail_panel/show_json/index.js | 0 .../show_json/show_json.container.js | 0 .../detail_panel/show_json/show_json.js | 0 .../index_list/detail_panel/summary/index.js | 0 .../detail_panel/summary/summary.container.js | 0 .../detail_panel/summary/summary.js | 58 ++-- .../sections/home/index_list/index.ts | 0 .../index_actions_context_menu/index.js | 0 .../index_actions_context_menu.container.js | 0 .../index_actions_context_menu.js | 126 +++---- .../sections/home/index_list/index_list.d.ts | 0 .../sections/home/index_list/index_list.js | 0 .../home/index_list/index_table/index.js | 0 .../index_table/index_table.container.js | 0 .../index_list/index_table/index_table.js | 314 +++++++++--------- .../sections/home/template_list/index.ts | 0 .../template_list/template_details/index.ts | 0 .../template_details/tabs/index.ts | 0 .../template_details/tabs/tab_aliases.tsx | 0 .../template_details/tabs/tab_mappings.tsx | 0 .../template_details/tabs/tab_settings.tsx | 0 .../template_details/tabs/tab_summary.tsx | 0 .../template_details/template_details.tsx | 3 +- .../home/template_list/template_list.tsx | 3 +- .../template_list/template_table/index.ts | 0 .../template_table/template_table.tsx | 3 +- .../sections/template_clone/index.ts | 0 .../template_clone/template_clone.tsx | 0 .../sections/template_create/index.ts | 0 .../template_create/template_create.tsx | 0 .../sections/template_edit/index.ts | 0 .../sections/template_edit/template_edit.tsx | 0 .../{app => application}/services/api.ts | 11 +- .../services/breadcrumbs.ts | 21 +- .../services/documentation.ts | 2 +- .../services/health_to_color.ts | 0 .../{app => application}/services/http.ts | 4 +- .../{app => application}/services/index.ts | 4 + .../services/navigation.ts | 0 .../services/notification.ts | 4 +- .../{app => application}/services/routing.ts | 0 .../services/sort_table.ts | 0 .../public/application/services/ui_metric.ts | 49 +++ .../services/use_request.ts | 0 .../store/actions/clear_cache_indices.js | 0 .../store/actions/clear_row_status.js | 0 .../store/actions/close_indices.js | 0 .../store/actions/delete_indices.js | 0 .../store/actions/detail_panel.js | 0 .../store/actions/edit_index_settings.js | 0 .../store/actions/extension_action.js | 0 .../store/actions/flush_indices.js | 0 .../store/actions/forcemerge_indices.js | 0 .../store/actions/freeze_indices.js | 0 .../store/actions/index.js | 0 .../store/actions/load_index_data.js | 0 .../store/actions/load_indices.js | 0 .../store/actions/open_indices.js | 0 .../store/actions/refresh_indices.js | 0 .../store/actions/reload_indices.js | 0 .../store/actions/table_state.js | 0 .../store/actions/unfreeze_indices.js | 0 .../store/actions/update_index_settings.js | 0 .../{app => application}/store/index.ts | 0 .../store/reducers/detail_panel.js | 89 +++++ .../store/reducers/index.js} | 2 +- .../store/reducers/index_management.js | 15 +- .../store/reducers/indices.js | 0 .../store/reducers/row_status.js | 0 .../store/reducers/table_state.js | 0 .../application/store/selectors/index.d.ts | 8 + .../store/selectors/index.js | 12 +- .../public/application/store/store.d.ts | 9 + .../{app => application}/store/store.js | 9 +- .../index_management/public/index.scss | 2 +- .../plugins/index_management/public/index.ts | 44 +-- .../public/index_management_extensions.ts | 72 ---- .../plugins/index_management/public/legacy.ts | 31 -- .../plugins/index_management/public/mocks.ts | 21 ++ .../plugins/index_management/public/plugin.ts | 112 +++++-- .../public/register_management_section.ts | 19 -- .../public/register_routes.ts | 34 -- .../services/extensions_service.mock.ts | 31 ++ .../public/services/extensions_service.ts | 97 ++++++ .../index_management/public/services/index.ts | 7 + .../{app/store/reducers/index.js => types.ts} | 2 +- x-pack/legacy/plugins/rollup/public/legacy.ts | 5 +- x-pack/legacy/plugins/rollup/public/plugin.ts | 11 +- 293 files changed, 1138 insertions(+), 903 deletions(-) delete mode 100644 x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.ts create mode 100644 x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx delete mode 100644 x-pack/legacy/plugins/index_management/public/app/index.tsx delete mode 100644 x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/detail_panel.js delete mode 100644 x-pack/legacy/plugins/index_management/public/app/services/ui_metric.ts delete mode 100644 x-pack/legacy/plugins/index_management/public/app/store/reducers/detail_panel.js rename x-pack/legacy/plugins/index_management/public/{app => application}/app.tsx (93%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/app_context.tsx rename x-pack/legacy/plugins/index_management/public/{app => application}/components/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/__jest__/client_integration/helpers/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/_index.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/_index.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/code_block.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/configuration_form.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/dynamic_mapping_section/dynamic_mapping_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/dynamic_mapping_section/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/meta_field_section/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/meta_field_section/meta_field_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/routing_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/source_field_section/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/configuration_form/source_field_section/source_field_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/_index.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/document_fields.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/document_fields_header.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/editor_toggle_controls.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/boost_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/coerce_number_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/coerce_shape_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/copy_to_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/doc_values_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_absolute.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_percentage.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/fielddata_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/format_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/ignore_malformed.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/ignore_z_value_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/index_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/locale_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/name_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/norms_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/null_value_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/orientation_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/path_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/similarity_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/split_queries_on_whitespace_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/store_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/term_vector_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/field_parameters/type_parameter.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/_field_list_item.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/_index.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/alias_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/dense_vector_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/scaled_float_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/token_count_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/delete_field_provider.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/_edit_field_form_row.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/_index.scss (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/advanced_parameters_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/basic_parameters_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/edit_field.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_container.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_form_row.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/edit_field/update_field_provider.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/alias_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/binary_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/boolean_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/completion_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/dense_vector_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/flattened_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/geo_point_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/geo_shape_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/ip_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/keyword_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/search_as_you_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/shape_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/text_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/fields_list.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/fields_list_item_container.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields/modal_confirmation_delete_fields.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields_json_editor.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/fields_tree_editor.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/search_fields/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/search_fields/search_result.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/fields_tree.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/load_mappings/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/load_mappings/load_from_json_button.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/load_mappings/load_mappings_provider.test.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/multiple_mappings_warning.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/templates_form/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/templates_form/templates_form.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/templates_form/templates_form_schema.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/tree/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/tree/tree.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/components/tree/tree_item.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/data_types_definition.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/default_values.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/field_options.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/field_options_i18n.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/mappings_editor.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/constants/parameters_definition.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/index_settings_context.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/error_reporter.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/extract_mappings_definition.test.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/extract_mappings_definition.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/mappings_validator.test.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/mappings_validator.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/search_fields.test.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/search_fields.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/serializers.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/utils.test.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/utils.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/lib/validators.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/mappings_editor.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/mappings_state.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/reducer.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/shared_imports.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/mappings_editor/types.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/no_match/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/no_match/no_match.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/page_error/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/page_error/page_error_forbidden.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/section_error.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/section_loading.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_delete_modal.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/step_aliases.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/step_logistics.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/step_mappings.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/step_review.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/step_settings.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/steps/use_json_step.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/template_form.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/template_form_schemas.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/template_steps.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/components/template_form/types.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/constants/detail_panel_tabs.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/constants/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/constants/refresh_intervals.ts (100%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/index.tsx rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/ace.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/edit_settings.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/flatten_object.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/flatten_panel_tree.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/index_status_labels.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/manage_angular_lifecycle.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/lib/render_badges.js (83%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/home.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/detail_panel.container.js (100%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.js rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.container.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/edit_settings_json/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/show_json/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/show_json/show_json.container.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/show_json/show_json.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/summary/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/summary/summary.container.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/detail_panel/summary/summary.js (72%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_actions_context_menu/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js (91%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_list.d.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_list.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_table/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_table/index_table.container.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/index_list/index_table/index_table.js (62%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/tabs/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/tabs/tab_aliases.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/tabs/tab_mappings.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/tabs/tab_settings.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/tabs/tab_summary.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_details/template_details.tsx (99%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_list.tsx (98%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_table/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/home/template_list/template_table/template_table.tsx (98%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/template_clone/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/template_clone/template_clone.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/template_create/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/template_create/template_create.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/template_edit/index.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/sections/template_edit/template_edit.tsx (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/api.ts (94%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/breadcrumbs.ts (81%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/documentation.ts (99%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/health_to_color.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/http.ts (86%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/index.ts (82%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/navigation.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/notification.ts (91%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/routing.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/services/sort_table.ts (100%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/services/ui_metric.ts rename x-pack/legacy/plugins/index_management/public/{app => application}/services/use_request.ts (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/clear_cache_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/clear_row_status.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/close_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/delete_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/detail_panel.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/edit_index_settings.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/extension_action.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/flush_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/forcemerge_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/freeze_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/index.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/load_index_data.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/load_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/open_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/refresh_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/reload_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/table_state.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/unfreeze_indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/actions/update_index_settings.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/index.ts (100%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/store/reducers/detail_panel.js rename x-pack/legacy/plugins/index_management/public/{app/store/store.d.ts => application/store/reducers/index.js} (82%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/reducers/index_management.js (63%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/reducers/indices.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/reducers/row_status.js (100%) rename x-pack/legacy/plugins/index_management/public/{app => application}/store/reducers/table_state.js (100%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/store/selectors/index.d.ts rename x-pack/legacy/plugins/index_management/public/{app => application}/store/selectors/index.js (93%) create mode 100644 x-pack/legacy/plugins/index_management/public/application/store/store.d.ts rename x-pack/legacy/plugins/index_management/public/{app => application}/store/store.js (71%) delete mode 100644 x-pack/legacy/plugins/index_management/public/index_management_extensions.ts delete mode 100644 x-pack/legacy/plugins/index_management/public/legacy.ts create mode 100644 x-pack/legacy/plugins/index_management/public/mocks.ts delete mode 100644 x-pack/legacy/plugins/index_management/public/register_management_section.ts delete mode 100644 x-pack/legacy/plugins/index_management/public/register_routes.ts create mode 100644 x-pack/legacy/plugins/index_management/public/services/extensions_service.mock.ts create mode 100644 x-pack/legacy/plugins/index_management/public/services/extensions_service.ts create mode 100644 x-pack/legacy/plugins/index_management/public/services/index.ts rename x-pack/legacy/plugins/index_management/public/{app/store/reducers/index.js => types.ts} (78%) diff --git a/src/plugins/management/public/index.ts b/src/plugins/management/public/index.ts index 4ece75bbf36da..9e59834303546 100644 --- a/src/plugins/management/public/index.ts +++ b/src/plugins/management/public/index.ts @@ -29,6 +29,7 @@ export { ManagementStart, RegisterManagementApp, RegisterManagementAppArgs, + ManagementAppMountParams, } from './types'; export { ManagementApp } from './management_app'; export { ManagementSection } from './management_section'; diff --git a/src/plugins/management/public/types.ts b/src/plugins/management/public/types.ts index 4dbea30ff062d..a8bdd5cca24a3 100644 --- a/src/plugins/management/public/types.ts +++ b/src/plugins/management/public/types.ts @@ -64,7 +64,7 @@ export type RegisterManagementApp = (managementApp: RegisterManagementAppArgs) = export type Unmount = () => Promise | void; -interface ManagementAppMountParams { +export interface ManagementAppMountParams { basePath: string; // base path for setting up your router element: HTMLElement; // element the section should render into setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js b/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js index cd107be408727..16ed0a7d695ad 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js +++ b/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/auto_follow_pattern_list/components/detail_panel/detail_panel.js @@ -7,7 +7,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from '@kbn/i18n/react'; -import { getIndexListUri } from '../../../../../../../../index_management/public/app/services/navigation'; +import { getIndexListUri } from '../../../../../../../../index_management/public/application/services/navigation'; import { EuiButtonEmpty, diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.js b/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.js index d4e43a1bd1840..e3bda2e67097d 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.js +++ b/x-pack/legacy/plugins/cross_cluster_replication/public/app/sections/home/follower_indices_list/components/detail_panel/detail_panel.js @@ -7,7 +7,7 @@ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from '@kbn/i18n/react'; -import { getIndexListUri } from '../../../../../../../../index_management/public/app/services/navigation'; +import { getIndexListUri } from '../../../../../../../../index_management/public/application/services/navigation'; import { EuiButton, diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/extend_index_management/index.js b/x-pack/legacy/plugins/cross_cluster_replication/public/extend_index_management/index.js index 549c71748e1be..809a7c3e87b75 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/public/extend_index_management/index.js +++ b/x-pack/legacy/plugins/cross_cluster_replication/public/extend_index_management/index.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { i18n } from '@kbn/i18n'; -import { addBadgeExtension } from '../../../index_management/public/index_management_extensions'; +import { extensionsService } from '../../../index_management/public'; import { get } from 'lodash'; const propertyPath = 'isFollowerIndex'; @@ -19,4 +19,4 @@ export const followerBadgeExtension = { filterExpression: 'isFollowerIndex:true', }; -addBadgeExtension(followerBadgeExtension); +extensionsService.addBadge(followerBadgeExtension); diff --git a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js b/x-pack/legacy/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js index cfae072b57a26..bcbae7e093f46 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/__jest__/extend_index_management.test.js @@ -7,6 +7,7 @@ import moment from 'moment-timezone'; import axios from 'axios'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; + import { mountWithIntl } from '../../../../test_utils/enzyme_helpers'; import { retryLifecycleActionExtension, @@ -26,6 +27,10 @@ initHttp(axios.create({ adapter: axiosXhrAdapter }), path => path); initUiMetric(() => () => {}); jest.mock('ui/new_platform'); +jest.mock('../../index_management/public', async () => { + const { indexManagementMock } = await import('../../index_management/public/mocks.ts'); + return indexManagementMock.createSetup(); +}); const indexWithoutLifecyclePolicy = { health: 'yellow', diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.js b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.js index eba7f75aa9baf..83d32eae1097d 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/application/sections/policy_table/components/policy_table/policy_table.js @@ -37,7 +37,7 @@ import { import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services'; -import { getIndexListUri } from '../../../../../../../../index_management/public/app/services/navigation'; +import { getIndexListUri } from '../../../../../../../../index_management/public/application/services/navigation'; import { BASE_PATH } from '../../../../../../../common/constants'; import { UIM_EDIT_CLICK } from '../../../../constants'; import { getPolicyPath } from '../../../../services/navigation'; diff --git a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.js b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.js index 422a7986aa057..6958c4ecce0cc 100644 --- a/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.js +++ b/x-pack/legacy/plugins/index_lifecycle_management/public/np_ready/extend_index_management/index.js @@ -9,13 +9,7 @@ import { get, every, any } from 'lodash'; import { i18n } from '@kbn/i18n'; import { EuiSearchBar } from '@elastic/eui'; -import { - addSummaryExtension, - addBannerExtension, - addActionExtension, - addFilterExtension, -} from '../../../../index_management/public/index_management_extensions'; - +import { extensionsService } from '../../../../index_management/public'; import { init as initUiMetric } from '../application/services/ui_metric'; import { init as initNotification } from '../application/services/notification'; import { retryLifecycleForIndex } from '../application/services/api'; @@ -27,13 +21,17 @@ const stepPath = 'ilm.step'; export const retryLifecycleActionExtension = ({ indices, - createUiStatsReporter, + usageCollection, toasts, fatalErrors, }) => { // These are hacks that we can remove once the New Platform migration is done. They're needed here // because API requests and API errors require them. - initUiMetric(createUiStatsReporter); + const getLegacyReporter = appName => (type, name) => { + usageCollection.reportUiStats(appName, type, name); + }; + + initUiMetric(getLegacyReporter); initNotification(toasts, fatalErrors); const allHaveErrors = every(indices, index => { @@ -207,11 +205,11 @@ export const ilmFilterExtension = indices => { }; export const addAllExtensions = () => { - addActionExtension(retryLifecycleActionExtension); - addActionExtension(removeLifecyclePolicyActionExtension); - addActionExtension(addLifecyclePolicyActionExtension); + extensionsService.addAction(retryLifecycleActionExtension); + extensionsService.addAction(removeLifecyclePolicyActionExtension); + extensionsService.addAction(addLifecyclePolicyActionExtension); - addBannerExtension(ilmBannerExtension); - addSummaryExtension(ilmSummaryExtension); - addFilterExtension(ilmFilterExtension); + extensionsService.addBanner(ilmBannerExtension); + extensionsService.addSummary(ilmSummaryExtension); + extensionsService.addFilter(ilmFilterExtension); }; diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/home.helpers.ts b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/home.helpers.ts index 4a4896347333c..e5f0b25d89c3e 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/home.helpers.ts +++ b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/home.helpers.ts @@ -13,13 +13,14 @@ import { findTestSubject, nextTick, } from '../../../../../../test_utils'; -import { IndexManagementHome } from '../../../public/app/sections/home'; +import { IndexManagementHome } from '../../../public/application/sections/home'; import { BASE_PATH } from '../../../common/constants'; -import { indexManagementStore } from '../../../public/app/store'; +import { indexManagementStore } from '../../../public/application/store'; import { Template } from '../../../common/types'; +import { WithAppDependencies, services } from './setup_environment'; const testBedConfig: TestBedConfig = { - store: indexManagementStore, + store: () => indexManagementStore(services as any), memoryRouter: { initialEntries: [`${BASE_PATH}indices`], componentRoutePath: `${BASE_PATH}:section(indices|templates)`, @@ -27,7 +28,7 @@ const testBedConfig: TestBedConfig = { doMountAsync: true, }; -const initTestBed = registerTestBed(IndexManagementHome, testBedConfig); +const initTestBed = registerTestBed(WithAppDependencies(IndexManagementHome), testBedConfig); export interface IdxMgmtHomeTestBed extends TestBed { findAction: (action: 'edit' | 'clone' | 'delete') => ReactWrapper; diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.ts b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.ts deleted file mode 100644 index d5ac185a63ccd..0000000000000 --- a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import axios from 'axios'; -import axiosXhrAdapter from 'axios/lib/adapters/xhr'; -import { init as initHttpRequests } from './http_requests'; -import { httpService } from '../../../public/app/services/http'; -import { breadcrumbService } from '../../../public/app/services/breadcrumbs'; -import { documentationService } from '../../../public/app/services/documentation'; -import { notificationService } from '../../../public/app/services/notification'; -import { uiMetricService } from '../../../public/app/services/ui_metric'; -import { createUiStatsReporter } from '../../../../../../../src/legacy/core_plugins/ui_metric/public'; - -/* eslint-disable @kbn/eslint/no-restricted-paths */ -import { notificationServiceMock } from '../../../../../../../src/core/public/notifications/notifications_service.mock'; -import { chromeServiceMock } from '../../../../../../../src/core/public/chrome/chrome_service.mock'; -import { docLinksServiceMock } from '../../../../../../../src/core/public/doc_links/doc_links_service.mock'; - -const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); - -export const setupEnvironment = () => { - // Mock initialization of services - // @ts-ignore - httpService.init(mockHttpClient); - breadcrumbService.init(chromeServiceMock.createStartContract(), ''); - documentationService.init(docLinksServiceMock.createStartContract()); - notificationService.init(notificationServiceMock.createStartContract()); - uiMetricService.init(createUiStatsReporter); - - const { server, httpRequestsMockHelpers } = initHttpRequests(); - - return { - server, - httpRequestsMockHelpers, - }; -}; diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx new file mode 100644 index 0000000000000..0212efe1f322d --- /dev/null +++ b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; +import axios from 'axios'; +import axiosXhrAdapter from 'axios/lib/adapters/xhr'; + +import { + notificationServiceMock, + docLinksServiceMock, +} from '../../../../../../../src/core/public/mocks'; +import { AppContextProvider } from '../../../public/application/app_context'; +import { httpService } from '../../../public/application/services/http'; +import { breadcrumbService } from '../../../public/application/services/breadcrumbs'; +import { documentationService } from '../../../public/application/services/documentation'; +import { notificationService } from '../../../public/application/services/notification'; +import { ExtensionsService } from '../../../public/services'; +import { UiMetricService } from '../../../public/application/services/ui_metric'; +import { setUiMetricService } from '../../../public/application/services/api'; +import { setExtensionsService } from '../../../public/application/store/selectors'; +import { init as initHttpRequests } from './http_requests'; + +const mockHttpClient = axios.create({ adapter: axiosXhrAdapter }); + +export const services = { + extensionsService: new ExtensionsService(), + uiMetricService: new UiMetricService('index_management'), +}; +services.uiMetricService.setup({ reportUiStats() {} } as any); +setExtensionsService(services.extensionsService); +setUiMetricService(services.uiMetricService); +const appDependencies = { services, core: {}, plugins: {} } as any; + +export const setupEnvironment = () => { + // Mock initialization of services + // @ts-ignore + httpService.setup(mockHttpClient); + breadcrumbService.setup(() => undefined); + documentationService.setup(docLinksServiceMock.createStartContract()); + notificationService.setup(notificationServiceMock.createSetupContract()); + + const { server, httpRequestsMockHelpers } = initHttpRequests(); + + return { + server, + httpRequestsMockHelpers, + }; +}; + +export const WithAppDependencies = (Comp: any) => (props: any) => ( + + + +); diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_clone.helpers.ts b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_clone.helpers.ts index 286e56b4349e4..cd1b67c08d934 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_clone.helpers.ts +++ b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_clone.helpers.ts @@ -6,9 +6,10 @@ import { registerTestBed, TestBedConfig } from '../../../../../../test_utils'; import { BASE_PATH } from '../../../common/constants'; -import { TemplateClone } from '../../../public/app/sections/template_clone'; +import { TemplateClone } from '../../../public/application/sections/template_clone'; import { formSetup } from './template_form.helpers'; import { TEMPLATE_NAME } from './constants'; +import { WithAppDependencies } from './setup_environment'; const testBedConfig: TestBedConfig = { memoryRouter: { @@ -18,6 +19,6 @@ const testBedConfig: TestBedConfig = { doMountAsync: true, }; -const initTestBed = registerTestBed(TemplateClone, testBedConfig); +const initTestBed = registerTestBed(WithAppDependencies(TemplateClone), testBedConfig); export const setup = formSetup.bind(null, initTestBed); diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_create.helpers.ts b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_create.helpers.ts index b1b5d51ef6a9d..8e62bc25d6bd1 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_create.helpers.ts +++ b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_create.helpers.ts @@ -6,8 +6,9 @@ import { registerTestBed, TestBedConfig } from '../../../../../../test_utils'; import { BASE_PATH } from '../../../common/constants'; -import { TemplateCreate } from '../../../public/app/sections/template_create'; +import { TemplateCreate } from '../../../public/application/sections/template_create'; import { formSetup, TestSubjects } from './template_form.helpers'; +import { WithAppDependencies } from './setup_environment'; const testBedConfig: TestBedConfig = { memoryRouter: { @@ -17,6 +18,9 @@ const testBedConfig: TestBedConfig = { doMountAsync: true, }; -const initTestBed = registerTestBed(TemplateCreate, testBedConfig); +const initTestBed = registerTestBed( + WithAppDependencies(TemplateCreate), + testBedConfig +); export const setup = formSetup.bind(null, initTestBed); diff --git a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_edit.helpers.ts b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_edit.helpers.ts index e8e19f637854d..cb1025234b48e 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_edit.helpers.ts +++ b/x-pack/legacy/plugins/index_management/__jest__/client_integration/helpers/template_edit.helpers.ts @@ -6,9 +6,10 @@ import { registerTestBed, TestBedConfig } from '../../../../../../test_utils'; import { BASE_PATH } from '../../../common/constants'; -import { TemplateEdit } from '../../../public/app/sections/template_edit'; +import { TemplateEdit } from '../../../public/application/sections/template_edit'; import { formSetup, TestSubjects } from './template_form.helpers'; import { TEMPLATE_NAME } from './constants'; +import { WithAppDependencies } from './setup_environment'; const testBedConfig: TestBedConfig = { memoryRouter: { @@ -18,6 +19,6 @@ const testBedConfig: TestBedConfig = { doMountAsync: true, }; -const initTestBed = registerTestBed(TemplateEdit, testBedConfig); +const initTestBed = registerTestBed(WithAppDependencies(TemplateEdit), testBedConfig); export const setup = formSetup.bind(null, initTestBed); diff --git a/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js b/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js index fe55b93d24a91..2b4fd89436458 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js +++ b/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js @@ -8,23 +8,25 @@ import React from 'react'; import axios from 'axios'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import { MemoryRouter } from 'react-router-dom'; -import { AppWithoutRouter } from '../../public/app/app'; +import { AppWithoutRouter } from '../../public/application/app'; +import { AppContextProvider } from '../../public/application/app_context'; import { Provider } from 'react-redux'; -import { loadIndicesSuccess } from '../../public/app/store/actions'; -import { breadcrumbService } from '../../public/app/services/breadcrumbs'; -import { uiMetricService } from '../../public/app/services/ui_metric'; -import { notificationService } from '../../public/app/services/notification'; -import { httpService } from '../../public/app/services/http'; -import { createUiStatsReporter } from '../../../../../../src/legacy/core_plugins/ui_metric/public'; -import { indexManagementStore } from '../../public/app/store'; +import { loadIndicesSuccess } from '../../public/application/store/actions'; +import { breadcrumbService } from '../../public/application/services/breadcrumbs'; +import { UiMetricService } from '../../public/application/services/ui_metric'; +import { notificationService } from '../../public/application/services/notification'; +import { httpService } from '../../public/application/services/http'; +import { setUiMetricService } from '../../public/application/services/api'; +import { indexManagementStore } from '../../public/application/store'; +import { setExtensionsService } from '../../public/application/store/selectors'; import { BASE_PATH, API_BASE_PATH } from '../../common/constants'; import { mountWithIntl } from '../../../../../test_utils/enzyme_helpers'; +import { ExtensionsService } from '../../public/services'; import sinon from 'sinon'; import { findTestSubject } from '@elastic/eui/lib/test'; /* eslint-disable @kbn/eslint/no-restricted-paths */ import { notificationServiceMock } from '../../../../../../src/core/public/notifications/notifications_service.mock'; -import { chromeServiceMock } from '../../../../../../src/core/public/chrome/chrome_service.mock'; jest.mock('ui/new_platform'); @@ -107,17 +109,29 @@ const namesText = rendered => { describe('index table', () => { beforeEach(() => { // Mock initialization of services + const services = { + extensionsService: new ExtensionsService(), + uiMetricService: new UiMetricService('index_management'), + }; + services.uiMetricService.setup({ reportUiStats() {} }); + setExtensionsService(services.extensionsService); + setUiMetricService(services.uiMetricService); + // @ts-ignore - httpService.init(mockHttpClient); - breadcrumbService.init(chromeServiceMock.createStartContract(), ''); - uiMetricService.init(createUiStatsReporter); - notificationService.init(notificationServiceMock.createStartContract()); + httpService.setup(mockHttpClient); + breadcrumbService.setup(() => undefined); + notificationService.setup(notificationServiceMock.createStartContract()); + + store = indexManagementStore(services); + + const appDependencies = { services, core: {}, plugins: {} }; - store = indexManagementStore(); component = ( - + + + ); @@ -141,6 +155,9 @@ describe('index table', () => { server.respondImmediately = true; }); afterEach(() => { + if (!server) { + return; + } server.restore(); }); @@ -294,6 +311,8 @@ describe('index table', () => { confirmButton.simulate('click'); snapshot(status(rendered, rowIndex)); }); + // Commenting the following 2 tests as it works in the browser (status changes to "closed" or "open") but the + // snapshot say the contrary. Need to be investigated. test('close index button works from context menu', done => { const modifiedIndices = indices.map(index => { return { diff --git a/x-pack/legacy/plugins/index_management/__jest__/lib/flatten_object.test.js b/x-pack/legacy/plugins/index_management/__jest__/lib/flatten_object.test.js index eb21459a3cbc7..0d6d5ee796627 100644 --- a/x-pack/legacy/plugins/index_management/__jest__/lib/flatten_object.test.js +++ b/x-pack/legacy/plugins/index_management/__jest__/lib/flatten_object.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { flattenObject } from '../../public/app/lib/flatten_object'; +import { flattenObject } from '../../public/application/lib/flatten_object'; describe('flatten_object', () => { test('it flattens an object', () => { const obj = { diff --git a/x-pack/legacy/plugins/index_management/public/app/index.tsx b/x-pack/legacy/plugins/index_management/public/app/index.tsx deleted file mode 100644 index 027839df2e20e..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/app/index.tsx +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { Provider } from 'react-redux'; -import { render, unmountComponentAtNode } from 'react-dom'; - -import { CoreStart } from '../../../../../../src/core/public'; - -import { App } from './app'; -import { indexManagementStore } from './store'; - -export const mountReactApp = (elem: HTMLElement | null, { core }: { core: CoreStart }): void => { - if (elem) { - const { i18n } = core; - const { Context: I18nContext } = i18n; - - render( - - - - - , - elem - ); - } -}; - -export const unmountReactApp = (elem: HTMLElement | null) => { - if (elem) { - unmountComponentAtNode(elem); - } -}; diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/detail_panel.js b/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/detail_panel.js deleted file mode 100644 index 0bfd32581ef4a..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/detail_panel.js +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Component, Fragment } from 'react'; -import { Route } from 'react-router-dom'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiCallOut, - EuiFlexGroup, - EuiFlexItem, - EuiFlyout, - EuiFlyoutBody, - EuiFlyoutFooter, - EuiFlyoutHeader, - EuiSpacer, - EuiTabs, - EuiTab, - EuiTitle, -} from '@elastic/eui'; -import { renderBadges } from '../../../../lib/render_badges'; -import { INDEX_OPEN } from '../../../../../../common/constants'; -import { - TAB_SUMMARY, - TAB_SETTINGS, - TAB_MAPPING, - TAB_STATS, - TAB_EDIT_SETTINGS, -} from '../../../../constants'; -import { IndexActionsContextMenu } from '../index_actions_context_menu'; -import { ShowJson } from './show_json'; -import { Summary } from './summary'; -import { EditSettingsJson } from './edit_settings_json'; - -const tabToHumanizedMap = { - [TAB_SUMMARY]: ( - - ), - [TAB_SETTINGS]: ( - - ), - [TAB_MAPPING]: ( - - ), - [TAB_STATS]: ( - - ), - [TAB_EDIT_SETTINGS]: ( - - ), -}; - -const tabs = [TAB_SUMMARY, TAB_SETTINGS, TAB_MAPPING, TAB_STATS, TAB_EDIT_SETTINGS]; - -export class DetailPanel extends Component { - renderTabs() { - const { panelType, indexName, index, openDetailPanel } = this.props; - return tabs.map((tab, i) => { - const isSelected = tab === panelType; - return ( - openDetailPanel({ panelType: tab, indexName })} - isSelected={isSelected} - data-test-subj={`detailPanelTab${isSelected ? 'Selected' : ''}`} - disabled={tab === TAB_STATS && index.status !== INDEX_OPEN} - key={i} - > - {tabToHumanizedMap[tab]} - - ); - }); - } - render() { - const { panelType, indexName, index, closeDetailPanel } = this.props; - if (!panelType) { - return null; - } - let component = null; - switch (panelType) { - case TAB_EDIT_SETTINGS: - component = ; - break; - case TAB_MAPPING: - case TAB_SETTINGS: - case TAB_STATS: - component = ; - break; - default: - component = ; - } - const content = index ? ( - - {component} - - - - ( - - } - /> - )} - /> - - - - - ) : ( - - - - } - color="danger" - iconType="cross" - > - - - - ); - return ( - - - -

- {indexName} - {renderBadges(index)} -

-
- {index ? {this.renderTabs()} : null} -
- {content} -
- ); - } -} diff --git a/x-pack/legacy/plugins/index_management/public/app/services/ui_metric.ts b/x-pack/legacy/plugins/index_management/public/app/services/ui_metric.ts deleted file mode 100644 index 4ea98fff1d70a..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/app/services/ui_metric.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { UIM_APP_NAME } from '../../../common/constants'; -import { - createUiStatsReporter, - UiStatsMetricType, -} from '../../../../../../../src/legacy/core_plugins/ui_metric/public'; - -class UiMetricService { - track?: ReturnType; - - public init = (getReporter: typeof createUiStatsReporter): void => { - this.track = getReporter(UIM_APP_NAME); - }; - - public trackMetric = (type: 'loaded' | 'click' | 'count', eventName: string): void => { - if (!this.track) throw Error('UiMetricService not initialized.'); - return this.track(type as UiStatsMetricType, eventName); - }; -} - -export const uiMetricService = new UiMetricService(); diff --git a/x-pack/legacy/plugins/index_management/public/app/store/reducers/detail_panel.js b/x-pack/legacy/plugins/index_management/public/app/store/reducers/detail_panel.js deleted file mode 100644 index 9ba73a1c61b03..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/app/store/reducers/detail_panel.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { handleActions } from 'redux-actions'; -import { - UIM_DETAIL_PANEL_SUMMARY_TAB, - UIM_DETAIL_PANEL_SETTINGS_TAB, - UIM_DETAIL_PANEL_MAPPING_TAB, - UIM_DETAIL_PANEL_STATS_TAB, - UIM_DETAIL_PANEL_EDIT_SETTINGS_TAB, -} from '../../../../common/constants'; -import { - TAB_SUMMARY, - TAB_SETTINGS, - TAB_MAPPING, - TAB_STATS, - TAB_EDIT_SETTINGS, -} from '../../constants'; -import { uiMetricService } from '../../services/ui_metric'; -import { openDetailPanel, closeDetailPanel } from '../actions/detail_panel'; -import { loadIndexDataSuccess } from '../actions/load_index_data'; -import { - updateIndexSettingsSuccess, - updateIndexSettingsError, -} from '../actions/update_index_settings'; -import { deleteIndicesSuccess } from '../actions/delete_indices'; - -const defaultState = {}; - -export const detailPanel = handleActions( - { - [deleteIndicesSuccess](state, action) { - const { indexNames } = action.payload; - const { indexName } = state; - if (indexNames.includes(indexName)) { - return {}; - } else { - return state; - } - }, - [openDetailPanel](state, action) { - const { panelType, indexName, title } = action.payload; - - const panelTypeToUiMetricMap = { - [TAB_SUMMARY]: UIM_DETAIL_PANEL_SUMMARY_TAB, - [TAB_SETTINGS]: UIM_DETAIL_PANEL_SETTINGS_TAB, - [TAB_MAPPING]: UIM_DETAIL_PANEL_MAPPING_TAB, - [TAB_STATS]: UIM_DETAIL_PANEL_STATS_TAB, - [TAB_EDIT_SETTINGS]: UIM_DETAIL_PANEL_EDIT_SETTINGS_TAB, - }; - - if (panelTypeToUiMetricMap[panelType]) { - uiMetricService.trackMetric('count', panelTypeToUiMetricMap[panelType]); - } - - return { - panelType: panelType || state.panelType || TAB_SUMMARY, - indexName, - title, - }; - }, - [closeDetailPanel]() { - return {}; - }, - [loadIndexDataSuccess](state, action) { - const { data } = action.payload; - const newState = { - ...state, - data, - }; - return newState; - }, - [updateIndexSettingsError](state, action) { - const { error } = action.payload; - const newState = { - ...state, - error, - }; - return newState; - }, - [updateIndexSettingsSuccess]() { - return {}; - }, - }, - defaultState -); diff --git a/x-pack/legacy/plugins/index_management/public/app/app.tsx b/x-pack/legacy/plugins/index_management/public/application/app.tsx similarity index 93% rename from x-pack/legacy/plugins/index_management/public/app/app.tsx rename to x-pack/legacy/plugins/index_management/public/application/app.tsx index 9ed824e184120..3b475f3baba04 100644 --- a/x-pack/legacy/plugins/index_management/public/app/app.tsx +++ b/x-pack/legacy/plugins/index_management/public/application/app.tsx @@ -11,9 +11,11 @@ import { IndexManagementHome } from './sections/home'; import { TemplateCreate } from './sections/template_create'; import { TemplateClone } from './sections/template_clone'; import { TemplateEdit } from './sections/template_edit'; -import { uiMetricService } from './services/ui_metric'; + +import { useServices } from './app_context'; export const App = () => { + const { uiMetricService } = useServices(); useEffect(() => uiMetricService.trackMetric('loaded', UIM_APP_LOAD), []); return ( diff --git a/x-pack/legacy/plugins/index_management/public/application/app_context.tsx b/x-pack/legacy/plugins/index_management/public/application/app_context.tsx new file mode 100644 index 0000000000000..12e0d362a2930 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/app_context.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { createContext, useContext } from 'react'; +import { CoreStart } from '../../../../../../src/core/public'; + +import { UsageCollectionSetup } from '../../../../../../src/plugins/usage_collection/public'; +import { IndexMgmtMetricsType } from '../types'; +import { UiMetricService, NotificationService, HttpService } from './services'; +import { ExtensionsService } from '../services'; + +const AppContext = createContext(undefined); + +export interface AppDependencies { + core: { + fatalErrors: CoreStart['fatalErrors']; + }; + plugins: { + usageCollection: UsageCollectionSetup; + }; + services: { + uiMetricService: UiMetricService; + extensionsService: ExtensionsService; + httpService: HttpService; + notificationService: NotificationService; + }; +} + +export const AppContextProvider = ({ + children, + value, +}: { + value: AppDependencies; + children: React.ReactNode; +}) => { + return {children}; +}; + +export const AppContextConsumer = AppContext.Consumer; + +export const useAppContext = () => { + const ctx = useContext(AppContext); + if (!ctx) { + throw new Error('"useAppContext" can only be called inside of AppContext.Provider!'); + } + return ctx; +}; + +export const useServices = () => useAppContext().services; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/_index.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/_index.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/_index.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/_index.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/_index.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/_index.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/_index.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/_index.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/code_block.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/code_block.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/code_block.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/code_block.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/configuration_form.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/configuration_form.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/dynamic_mapping_section/dynamic_mapping_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/dynamic_mapping_section/dynamic_mapping_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/dynamic_mapping_section/dynamic_mapping_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/dynamic_mapping_section/dynamic_mapping_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/dynamic_mapping_section/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/dynamic_mapping_section/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/dynamic_mapping_section/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/dynamic_mapping_section/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/meta_field_section/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/meta_field_section/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/meta_field_section/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/meta_field_section/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/meta_field_section/meta_field_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/meta_field_section/meta_field_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/meta_field_section/meta_field_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/meta_field_section/meta_field_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/routing_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/routing_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/routing_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/routing_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/source_field_section/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/source_field_section/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/source_field_section/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/source_field_section/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/source_field_section/source_field_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/source_field_section/source_field_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/configuration_form/source_field_section/source_field_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/source_field_section/source_field_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/_index.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/_index.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/_index.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/_index.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/document_fields.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/document_fields.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields_header.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/document_fields_header.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields_header.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/document_fields_header.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/editor_toggle_controls.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/editor_toggle_controls.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/editor_toggle_controls.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/editor_toggle_controls.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzer_parameter_selects.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/analyzers_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/boost_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/boost_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/boost_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/boost_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/coerce_number_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/coerce_number_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/coerce_number_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/coerce_number_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/coerce_shape_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/coerce_shape_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/coerce_shape_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/coerce_shape_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/copy_to_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/copy_to_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/copy_to_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/copy_to_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/doc_values_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/doc_values_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/doc_values_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/doc_values_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/dynamic_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/eager_global_ordinals_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/enabled_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_absolute.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_absolute.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_absolute.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_absolute.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_percentage.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_percentage.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_percentage.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/fielddata_frequency_filter_percentage.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/fielddata_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/fielddata_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/fielddata_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/fielddata_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/format_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/format_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/format_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/format_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/ignore_malformed.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/ignore_malformed.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/ignore_malformed.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/ignore_malformed.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/ignore_z_value_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/ignore_z_value_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/ignore_z_value_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/ignore_z_value_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/index_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/index_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/index_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/index_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/locale_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/locale_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/locale_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/locale_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/max_shingle_size_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/name_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/name_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/name_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/name_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/norms_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/norms_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/norms_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/norms_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/null_value_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/null_value_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/null_value_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/null_value_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/orientation_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/orientation_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/orientation_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/orientation_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/path_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/path_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/path_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/path_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/relations_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/similarity_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/similarity_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/similarity_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/similarity_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/split_queries_on_whitespace_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/split_queries_on_whitespace_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/split_queries_on_whitespace_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/split_queries_on_whitespace_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/store_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/store_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/store_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/store_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/term_vector_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/term_vector_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/term_vector_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/term_vector_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/type_parameter.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/type_parameter.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/field_parameters/type_parameter.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/type_parameter.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/_field_list_item.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/_field_list_item.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/_field_list_item.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/_field_list_item.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/_index.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/_index.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/_index.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/_index.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/alias_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/alias_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/alias_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/alias_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/dense_vector_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/dense_vector_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/dense_vector_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/dense_vector_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/scaled_float_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/scaled_float_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/scaled_float_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/scaled_float_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/token_count_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/token_count_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/token_count_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/token_count_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/delete_field_provider.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/delete_field_provider.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/delete_field_provider.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/delete_field_provider.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/_edit_field_form_row.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/_edit_field_form_row.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/_edit_field_form_row.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/_edit_field_form_row.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/_index.scss b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/_index.scss similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/_index.scss rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/_index.scss diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/advanced_parameters_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/advanced_parameters_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/advanced_parameters_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/advanced_parameters_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/basic_parameters_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/basic_parameters_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/basic_parameters_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/basic_parameters_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_container.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_container.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_container.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_container.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_form_row.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_form_row.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_form_row.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_form_row.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/update_field_provider.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/update_field_provider.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/edit_field/update_field_provider.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/update_field_provider.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/alias_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/alias_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/alias_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/alias_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/binary_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/binary_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/binary_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/binary_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/boolean_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/boolean_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/boolean_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/boolean_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/completion_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/completion_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/completion_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/completion_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/date_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/dense_vector_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/dense_vector_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/dense_vector_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/dense_vector_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/flattened_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/flattened_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/flattened_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/flattened_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/geo_point_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/geo_point_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/geo_point_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/geo_point_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/geo_shape_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/geo_shape_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/geo_shape_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/geo_shape_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/ip_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/ip_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/ip_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/ip_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/join_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/keyword_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/keyword_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/keyword_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/keyword_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/nested_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/numeric_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/object_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/range_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/search_as_you_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/search_as_you_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/search_as_you_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/search_as_you_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/shape_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/shape_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/shape_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/shape_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/text_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/text_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/text_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/text_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/token_count_type.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list_item_container.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item_container.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/fields_list_item_container.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item_container.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/modal_confirmation_delete_fields.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/modal_confirmation_delete_fields.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields/modal_confirmation_delete_fields.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/modal_confirmation_delete_fields.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields_json_editor.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields_json_editor.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields_json_editor.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields_json_editor.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields_tree_editor.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields_tree_editor.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/fields_tree_editor.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields_tree_editor.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/search_fields/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/search_fields/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/search_fields/search_result.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/search_result.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/search_fields/search_result.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/search_result.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/fields_tree.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/fields_tree.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/fields_tree.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/fields_tree.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_from_json_button.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/load_from_json_button.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_from_json_button.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/load_from_json_button.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.test.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/load_mappings_provider.test.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.test.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/load_mappings_provider.test.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/multiple_mappings_warning.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/multiple_mappings_warning.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/multiple_mappings_warning.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/multiple_mappings_warning.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/templates_form/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/templates_form/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/templates_form/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/templates_form/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/templates_form/templates_form.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/templates_form/templates_form.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/templates_form/templates_form.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/templates_form/templates_form.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/templates_form/templates_form_schema.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/templates_form/templates_form_schema.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/templates_form/templates_form_schema.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/templates_form/templates_form_schema.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/tree/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/tree/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/tree/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/tree/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/tree/tree.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/tree/tree.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/tree/tree.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/tree/tree.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/tree/tree_item.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/tree/tree_item.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/tree/tree_item.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/components/tree/tree_item.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/data_types_definition.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/data_types_definition.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/data_types_definition.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/data_types_definition.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/default_values.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/default_values.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/default_values.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/default_values.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/field_options.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/field_options.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/field_options.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/field_options.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/field_options_i18n.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/field_options_i18n.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/field_options_i18n.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/field_options_i18n.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/mappings_editor.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/mappings_editor.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/mappings_editor.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/mappings_editor.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/index_settings_context.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/index_settings_context.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/index_settings_context.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/index_settings_context.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/error_reporter.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/error_reporter.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/error_reporter.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/error_reporter.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.test.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/extract_mappings_definition.test.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.test.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/extract_mappings_definition.test.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/extract_mappings_definition.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/extract_mappings_definition.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.test.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.test.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.test.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.test.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/search_fields.test.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/search_fields.test.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/search_fields.test.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/search_fields.test.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/search_fields.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/search_fields.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/search_fields.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/search_fields.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/serializers.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/serializers.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/serializers.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/serializers.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/utils.test.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/utils.test.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/utils.test.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/utils.test.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/utils.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/utils.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/utils.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/utils.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/validators.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/validators.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/validators.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/lib/validators.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_editor.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_editor.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_state.tsx b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/mappings_state.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_state.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/mappings_state.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/reducer.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/reducer.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/reducer.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/reducer.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/shared_imports.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/shared_imports.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/shared_imports.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/shared_imports.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/types.ts b/x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/types.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/types.ts rename to x-pack/legacy/plugins/index_management/public/application/components/mappings_editor/types.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/no_match/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/no_match/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/no_match/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/no_match/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/no_match/no_match.tsx b/x-pack/legacy/plugins/index_management/public/application/components/no_match/no_match.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/no_match/no_match.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/no_match/no_match.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/page_error/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/page_error/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/page_error/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/page_error/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/page_error/page_error_forbidden.tsx b/x-pack/legacy/plugins/index_management/public/application/components/page_error/page_error_forbidden.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/page_error/page_error_forbidden.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/page_error/page_error_forbidden.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/section_error.tsx b/x-pack/legacy/plugins/index_management/public/application/components/section_error.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/section_error.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/section_error.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/section_loading.tsx b/x-pack/legacy/plugins/index_management/public/application/components/section_loading.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/section_loading.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/section_loading.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_delete_modal.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_delete_modal.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_delete_modal.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_delete_modal.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/template_form/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/index.ts b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/index.ts rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_aliases.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_aliases.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_aliases.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_aliases.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_logistics.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_logistics.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_logistics.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_logistics.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_mappings.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_mappings.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_mappings.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_mappings.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_review.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_review.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_review.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_review.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_settings.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_settings.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/step_settings.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/step_settings.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/use_json_step.ts b/x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/use_json_step.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/steps/use_json_step.ts rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/steps/use_json_step.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/template_form.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/template_form.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/template_form.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/template_form.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/template_form_schemas.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/template_form_schemas.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/template_form_schemas.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/template_form_schemas.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/template_steps.tsx b/x-pack/legacy/plugins/index_management/public/application/components/template_form/template_steps.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/template_steps.tsx rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/template_steps.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/components/template_form/types.ts b/x-pack/legacy/plugins/index_management/public/application/components/template_form/types.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/components/template_form/types.ts rename to x-pack/legacy/plugins/index_management/public/application/components/template_form/types.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/constants/detail_panel_tabs.ts b/x-pack/legacy/plugins/index_management/public/application/constants/detail_panel_tabs.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/constants/detail_panel_tabs.ts rename to x-pack/legacy/plugins/index_management/public/application/constants/detail_panel_tabs.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/constants/index.ts b/x-pack/legacy/plugins/index_management/public/application/constants/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/constants/index.ts rename to x-pack/legacy/plugins/index_management/public/application/constants/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/constants/refresh_intervals.ts b/x-pack/legacy/plugins/index_management/public/application/constants/refresh_intervals.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/constants/refresh_intervals.ts rename to x-pack/legacy/plugins/index_management/public/application/constants/refresh_intervals.ts diff --git a/x-pack/legacy/plugins/index_management/public/application/index.tsx b/x-pack/legacy/plugins/index_management/public/application/index.tsx new file mode 100644 index 0000000000000..b9859903f1434 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/index.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { Provider } from 'react-redux'; +import { render, unmountComponentAtNode } from 'react-dom'; + +import { CoreStart } from '../../../../../../src/core/public'; + +import { AppContextProvider, AppDependencies } from './app_context'; +import { App } from './app'; +import { indexManagementStore } from './store'; + +export const renderApp = ( + elem: HTMLElement | null, + { core, dependencies }: { core: CoreStart; dependencies: AppDependencies } +) => { + if (!elem) { + return () => undefined; + } + + const { i18n } = core; + const { Context: I18nContext } = i18n; + const { services } = dependencies; + + render( + + + + + + + , + elem + ); + + return () => { + unmountComponentAtNode(elem); + }; +}; + +export { AppDependencies }; diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/ace.js b/x-pack/legacy/plugins/index_management/public/application/lib/ace.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/lib/ace.js rename to x-pack/legacy/plugins/index_management/public/application/lib/ace.js diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/edit_settings.js b/x-pack/legacy/plugins/index_management/public/application/lib/edit_settings.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/lib/edit_settings.js rename to x-pack/legacy/plugins/index_management/public/application/lib/edit_settings.js diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/flatten_object.js b/x-pack/legacy/plugins/index_management/public/application/lib/flatten_object.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/lib/flatten_object.js rename to x-pack/legacy/plugins/index_management/public/application/lib/flatten_object.js diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/flatten_panel_tree.js b/x-pack/legacy/plugins/index_management/public/application/lib/flatten_panel_tree.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/lib/flatten_panel_tree.js rename to x-pack/legacy/plugins/index_management/public/application/lib/flatten_panel_tree.js diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/index_status_labels.js b/x-pack/legacy/plugins/index_management/public/application/lib/index_status_labels.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/lib/index_status_labels.js rename to x-pack/legacy/plugins/index_management/public/application/lib/index_status_labels.js diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/manage_angular_lifecycle.ts b/x-pack/legacy/plugins/index_management/public/application/lib/manage_angular_lifecycle.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/lib/manage_angular_lifecycle.ts rename to x-pack/legacy/plugins/index_management/public/application/lib/manage_angular_lifecycle.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/lib/render_badges.js b/x-pack/legacy/plugins/index_management/public/application/lib/render_badges.js similarity index 83% rename from x-pack/legacy/plugins/index_management/public/app/lib/render_badges.js rename to x-pack/legacy/plugins/index_management/public/application/lib/render_badges.js index 175b88bd31f6c..fbca65fe5dba6 100644 --- a/x-pack/legacy/plugins/index_management/public/app/lib/render_badges.js +++ b/x-pack/legacy/plugins/index_management/public/application/lib/render_badges.js @@ -7,10 +7,10 @@ import React, { Fragment } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiBadge, EuiSearchBar } from '@elastic/eui'; -import { getBadgeExtensions } from '../../index_management_extensions'; -export const renderBadges = (index, filterChanged) => { + +export const renderBadges = (index, filterChanged, extensionsService) => { const badgeLabels = []; - getBadgeExtensions().forEach(({ matchIndex, label, color, filterExpression }) => { + extensionsService.badges.forEach(({ matchIndex, label, color, filterExpression }) => { if (matchIndex(index)) { const clickHandler = () => { filterChanged && diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/home.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/home.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/home.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/home.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/detail_panel.container.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.container.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/detail_panel.container.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.container.js diff --git a/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.js new file mode 100644 index 0000000000000..e0128b1d51d02 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/detail_panel.js @@ -0,0 +1,167 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Fragment } from 'react'; +import { Route } from 'react-router-dom'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiCallOut, + EuiFlexGroup, + EuiFlexItem, + EuiFlyout, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, + EuiSpacer, + EuiTabs, + EuiTab, + EuiTitle, +} from '@elastic/eui'; +import { renderBadges } from '../../../../lib/render_badges'; +import { INDEX_OPEN } from '../../../../../../common/constants'; +import { + TAB_SUMMARY, + TAB_SETTINGS, + TAB_MAPPING, + TAB_STATS, + TAB_EDIT_SETTINGS, +} from '../../../../constants'; +import { IndexActionsContextMenu } from '../index_actions_context_menu'; +import { ShowJson } from './show_json'; +import { Summary } from './summary'; +import { EditSettingsJson } from './edit_settings_json'; +import { useServices } from '../../../../app_context'; + +const tabToHumanizedMap = { + [TAB_SUMMARY]: ( + + ), + [TAB_SETTINGS]: ( + + ), + [TAB_MAPPING]: ( + + ), + [TAB_STATS]: ( + + ), + [TAB_EDIT_SETTINGS]: ( + + ), +}; + +const tabs = [TAB_SUMMARY, TAB_SETTINGS, TAB_MAPPING, TAB_STATS, TAB_EDIT_SETTINGS]; + +export const DetailPanel = ({ panelType, indexName, index, openDetailPanel, closeDetailPanel }) => { + const { extensionsService } = useServices(); + + const renderTabs = () => { + return tabs.map((tab, i) => { + const isSelected = tab === panelType; + return ( + openDetailPanel({ panelType: tab, indexName })} + isSelected={isSelected} + data-test-subj={`detailPanelTab${isSelected ? 'Selected' : ''}`} + disabled={tab === TAB_STATS && index.status !== INDEX_OPEN} + key={i} + > + {tabToHumanizedMap[tab]} + + ); + }); + }; + + if (!panelType) { + return null; + } + + let component = null; + switch (panelType) { + case TAB_EDIT_SETTINGS: + component = ; + break; + case TAB_MAPPING: + case TAB_SETTINGS: + case TAB_STATS: + component = ; + break; + default: + component = ; + } + + const content = index ? ( + + {component} + + + + ( + + } + /> + )} + /> + + + + + ) : ( + + + + } + color="danger" + iconType="cross" + > + + + + ); + + return ( + + + +

+ {indexName} + {renderBadges(index, undefined, extensionsService)} +

+
+ {index ? {renderTabs()} : null} +
+ {content} +
+ ); +}; diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.container.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.container.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.container.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.container.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/edit_settings_json/edit_settings_json.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/edit_settings_json/index.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/edit_settings_json/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/edit_settings_json/index.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/edit_settings_json/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/index.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/index.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/show_json/index.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/show_json/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/show_json/index.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/show_json/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/show_json/show_json.container.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/show_json/show_json.container.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/show_json/show_json.container.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/show_json/show_json.container.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/show_json/show_json.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/show_json/show_json.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/show_json/show_json.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/show_json/show_json.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/index.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/index.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/summary.container.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.container.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/summary.container.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.container.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/summary.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.js similarity index 72% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/summary.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.js index a49dc6079e3c5..e49b3c353931e 100644 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/detail_panel/summary/summary.js +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/detail_panel/summary/summary.js @@ -6,7 +6,6 @@ import React, { Fragment } from 'react'; import { i18n } from '@kbn/i18n'; -import { healthToColor } from '../../../../../services'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFlexGroup, @@ -19,7 +18,9 @@ import { EuiSpacer, EuiTitle, } from '@elastic/eui'; -import { getSummaryExtensions } from '../../../../../../index_management_extensions'; +import { healthToColor } from '../../../../../services'; +import { AppContextConsumer } from '../../../../../app_context'; + const getHeaders = () => { return { health: i18n.translate('xpack.idxMgmt.summary.headers.healthHeader', { @@ -53,9 +54,9 @@ const getHeaders = () => { }; export class Summary extends React.PureComponent { - getAdditionalContent() { + getAdditionalContent(extensionsService) { const { index } = this.props; - const extensions = getSummaryExtensions(); + const extensions = extensionsService.summaries; return extensions.map((summaryExtension, i) => { return ( @@ -65,6 +66,7 @@ export class Summary extends React.PureComponent { ); }); } + buildRows() { const { index } = this.props; const headers = getHeaders(); @@ -99,26 +101,36 @@ export class Summary extends React.PureComponent { } render() { - const { left, right } = this.buildRows(); - const additionalContent = this.getAdditionalContent(); return ( - - -

- -

-
- - - - {left} - - - {right} - - - {additionalContent} -
+ + {({ services }) => { + const { left, right } = this.buildRows(); + const additionalContent = this.getAdditionalContent(services.extensionsService); + + return ( + + +

+ +

+
+ + + + {left} + + + {right} + + + {additionalContent} +
+ ); + }} +
); } } diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js similarity index 91% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js index 5ed651e3125cf..8f794ce1ed612 100644 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js @@ -23,21 +23,9 @@ import { EuiCheckbox, } from '@elastic/eui'; -// We will be able to remove these after the NP migration is complete. -import { fatalError } from 'ui/notify'; -import { createUiStatsReporter } from '../../../../../../../../../../src/legacy/core_plugins/ui_metric/public'; -import { httpService } from '../../../../services/http'; -import { notificationService } from '../../../../services/notification'; - import { flattenPanelTree } from '../../../../lib/flatten_panel_tree'; import { INDEX_OPEN } from '../../../../../../common/constants'; -import { getActionExtensions } from '../../../../../index_management_extensions'; - -// We will be able to remove this after the NP migration is complete and we can just inject the -// NP fatalErrors service.. -const getNewPlatformCompatibleFatalErrorService = () => ({ - add: fatalError.bind(fatalError), -}); +import { AppContextConsumer } from '../../../../app_context'; export class IndexActionsContextMenu extends Component { constructor(props) { @@ -58,7 +46,11 @@ export class IndexActionsContextMenu extends Component { confirmAction = isActionConfirmed => { this.setState({ isActionConfirmed }); }; - panels() { + panels({ + core: { fatalErrors }, + services: { extensionsService, httpService, notificationService }, + plugins: { usageCollection }, + }) { const { closeIndices, openIndices, @@ -222,7 +214,7 @@ export class IndexActionsContextMenu extends Component { this.setState({ renderConfirmModal: this.renderConfirmDeleteModal }); }, }); - getActionExtensions().forEach(actionExtension => { + extensionsService.actions.forEach(actionExtension => { const actionExtensionDefinition = actionExtension({ indices, reloadIndices, @@ -231,12 +223,11 @@ export class IndexActionsContextMenu extends Component { // dependencies, but they're not available unless the app's "setup" lifecycle stage occurs. // Within the old platform, "setup" only occurs once the user actually visits the app. // Once ILM and IM have been moved out of legacy this hack won't be necessary. - createUiStatsReporter, + usageCollection, toasts: notificationService.toasts, - fatalErrors: getNewPlatformCompatibleFatalErrorService(), + fatalErrors, httpClient: httpService.httpClient, }); - if (actionExtensionDefinition) { const { buttonLabel, @@ -721,52 +712,61 @@ export class IndexActionsContextMenu extends Component { }; render() { - const { indexNames } = this.props; - const selectedIndexCount = indexNames.length; - const { - iconSide = 'right', - anchorPosition = 'rightUp', - label = i18n.translate('xpack.idxMgmt.indexActionsMenu.manageButtonLabel', { - defaultMessage: 'Manage {selectedIndexCount, plural, one {index} other {indices}}', - values: { selectedIndexCount }, - }), - iconType = 'arrowDown', - } = this.props; - const panels = this.panels(); - const button = ( - - {label} - - ); - return ( -
- {this.state.renderConfirmModal - ? this.state.renderConfirmModal(this.closeConfirmModal) - : null} - - - -
+ + {appDependencies => { + const { indexNames } = this.props; + const selectedIndexCount = indexNames.length; + const { + iconSide = 'right', + anchorPosition = 'rightUp', + label = i18n.translate('xpack.idxMgmt.indexActionsMenu.manageButtonLabel', { + defaultMessage: 'Manage {selectedIndexCount, plural, one {index} other {indices}}', + values: { selectedIndexCount }, + }), + iconType = 'arrowDown', + } = this.props; + + const panels = this.panels(appDependencies); + + const button = ( + + {label} + + ); + + return ( +
+ {this.state.renderConfirmModal + ? this.state.renderConfirmModal(this.closeConfirmModal) + : null} + + + +
+ ); + }} +
); } } diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_list.d.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_list.d.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_list.d.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_list.d.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_list.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_list.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_list.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_list.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index_table.container.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.container.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index_table.container.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.container.js diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index_table.js b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js similarity index 62% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index_table.js rename to x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js index e043323c5b290..b659e2ec86a9b 100644 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/index_list/index_table/index_table.js +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js @@ -38,12 +38,7 @@ import { import { UIM_SHOW_DETAILS_CLICK } from '../../../../../../common/constants'; import { REFRESH_RATE_INDEX_LIST } from '../../../../constants'; import { healthToColor } from '../../../../services'; -import { uiMetricService } from '../../../../services/ui_metric'; -import { - getBannerExtensions, - getFilterExtensions, - getToggleExtensions, -} from '../../../../../index_management_extensions'; +import { AppContextConsumer } from '../../../../app_context'; import { renderBadges } from '../../../../lib/render_badges'; import { NoMatch, PageErrorForbidden } from '../../../../components'; import { IndexActionsContextMenu } from '../index_actions_context_menu'; @@ -153,9 +148,9 @@ export class IndexTable extends Component { this.setState({ filterError: null }); } }; - getFilters = () => { + getFilters = extensionsService => { const { allIndices } = this.props; - return getFilterExtensions().reduce((accum, filterExtension) => { + return extensionsService.filters.reduce((accum, filterExtension) => { const filtersToAdd = filterExtension(allIndices); return [...accum, ...filtersToAdd]; }, []); @@ -218,7 +213,7 @@ export class IndexTable extends Component { }); } - buildRowCell(fieldName, value, index) { + buildRowCell(fieldName, value, index, appServices) { const { openDetailPanel, filterChanged } = this.props; if (fieldName === 'health') { return {value}; @@ -228,20 +223,20 @@ export class IndexTable extends Component { { - uiMetricService.trackMetric('click', UIM_SHOW_DETAILS_CLICK); + appServices.uiMetricService.trackMetric('click', UIM_SHOW_DETAILS_CLICK); openDetailPanel(value); }} > {value} - {renderBadges(index, filterChanged)} + {renderBadges(index, filterChanged, appServices.extensionsService)}
); } return value; } - buildRowCells(index) { + buildRowCells(index, appServices) { return Object.keys(HEADERS).map(fieldName => { const { name } = index; const value = index[fieldName]; @@ -255,7 +250,9 @@ export class IndexTable extends Component { data-test-subj={`indexTableCell-${fieldName}`} >
- {this.buildRowCell(fieldName, value, index)} + + {this.buildRowCell(fieldName, value, index, appServices)} +
); @@ -268,7 +265,7 @@ export class IndexTable extends Component { className={'indTable__cell--' + fieldName} header={fieldName} > - {this.buildRowCell(fieldName, value, index)} + {this.buildRowCell(fieldName, value, index, appServices)} ); }); @@ -310,9 +307,9 @@ export class IndexTable extends Component { ); } - renderBanners() { + renderBanners(extensionsService) { const { allIndices = [], filterChanged } = this.props; - return getBannerExtensions().map((bannerExtension, i) => { + return extensionsService.banners.map((bannerExtension, i) => { const bannerData = bannerExtension(allIndices); if (!bannerData) { return null; @@ -335,7 +332,8 @@ export class IndexTable extends Component { ); }); } - buildRows() { + + buildRows(appServices) { const { indices = [], detailPanelIndexName } = this.props; return indices.map(index => { const { name } = index; @@ -360,7 +358,7 @@ export class IndexTable extends Component { })} /> - {this.buildRowCells(index)} + {this.buildRowCells(index, appServices)} ); }); @@ -383,6 +381,7 @@ export class IndexTable extends Component { onItemSelectionChanged = selectedIndices => { this.setState({ selectedIndices }); }; + renderToggleControl({ name, label }) { const { toggleNameToVisibleMap, toggleChanged } = this.props; return ( @@ -397,6 +396,7 @@ export class IndexTable extends Component { ); } + render() { const { filter, @@ -434,145 +434,157 @@ export class IndexTable extends Component { } return ( - - - - - - - - - - - {(indicesLoading && allIndices.length === 0) || indicesError ? null : ( - - {getToggleExtensions().map(toggle => { - return this.renderToggleControl(toggle); - })} - - showSystemIndicesChanged(event.target.checked)} - label={ + + {({ services }) => { + const { extensionsService } = services; + + return ( + + + + + - } - /> + + + + + {(indicesLoading && allIndices.length === 0) || indicesError ? null : ( + + {extensionsService.toggles.map(toggle => { + return this.renderToggleControl(toggle); + })} + + showSystemIndicesChanged(event.target.checked)} + label={ + + } + /> + + + )} - )} - - - - {this.renderBanners()} - {indicesError && this.renderError()} - - {atLeastOneItemSelected ? ( - - ( - { - this.setState({ selectedIndicesMap: {} }); - }} - /> + + {this.renderBanners(extensionsService)} + {indicesError && this.renderError()} + + {atLeastOneItemSelected ? ( + + ( + { + this.setState({ selectedIndicesMap: {} }); + }} + /> + )} + /> + + ) : null} + {(indicesLoading && allIndices.length === 0) || indicesError ? null : ( + + + 0 + ? this.getFilters(extensionsService) + : null + } + defaultQuery={filter} + query={filter} + box={{ + incremental: true, + placeholder: i18n.translate( + 'xpack.idxMgmt.indexTable.systemIndicesSearchInputPlaceholder', + { + defaultMessage: 'Search', + } + ), + }} + aria-label={i18n.translate( + 'xpack.idxMgmt.indexTable.systemIndicesSearchIndicesAriaLabel', + { + defaultMessage: 'Search indices', + } + )} + data-test-subj="indexTableFilterInput" + onChange={this.onFilterChanged} + /> + + + { + loadIndices(); + }} + iconType="refresh" + data-test-subj="reloadIndicesButton" + > + + + + )} - /> - - ) : null} - {(indicesLoading && allIndices.length === 0) || indicesError ? null : ( - - - 0 ? this.getFilters() : null} - defaultQuery={filter} - query={filter} - box={{ - incremental: true, - placeholder: i18n.translate( - 'xpack.idxMgmt.indexTable.systemIndicesSearchInputPlaceholder', - { - defaultMessage: 'Search', - } - ), - }} - aria-label={i18n.translate( - 'xpack.idxMgmt.indexTable.systemIndicesSearchIndicesAriaLabel', - { - defaultMessage: 'Search indices', - } - )} - data-test-subj="indexTableFilterInput" - onChange={this.onFilterChanged} - /> - - - { - loadIndices(); - }} - iconType="refresh" - data-test-subj="reloadIndicesButton" - > - - - + + {this.renderFilterError()} + + {indices.length > 0 ? ( +
+ + + + + + + + + + + {this.buildHeader()} + + {this.buildRows(services)} + +
+ ) : ( + emptyState + )} + + {indices.length > 0 ? this.renderPager() : null}
- )} - - {this.renderFilterError()} - - {indices.length > 0 ? ( -
- - - - - - - - - - - {this.buildHeader()} - - {this.buildRows()} - -
- ) : ( - emptyState - )} - - {indices.length > 0 ? this.renderPager() : null} - + ); + }} + ); } } diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_aliases.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_aliases.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_aliases.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_aliases.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_mappings.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_mappings.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_mappings.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_mappings.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_settings.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_settings.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_settings.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_settings.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_summary.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_summary.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/tabs/tab_summary.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_summary.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/template_details.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/template_details.tsx similarity index 99% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/template_details.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/template_details.tsx index eaa0a331afcef..ced8bd97e744b 100644 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_details/template_details.tsx +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_details/template_details.tsx @@ -34,8 +34,8 @@ import { Template } from '../../../../../../common/types'; import { TemplateDeleteModal, SectionLoading, SectionError, Error } from '../../../../components'; import { loadIndexTemplate } from '../../../../services/api'; import { decodePath } from '../../../../services/routing'; -import { uiMetricService } from '../../../../services/ui_metric'; import { SendRequestResponse } from '../../../../../shared_imports'; +import { useServices } from '../../../../app_context'; import { TabSummary, TabMappings, TabSettings, TabAliases } from './tabs'; interface Props { @@ -101,6 +101,7 @@ export const TemplateDetails: React.FunctionComponent = ({ cloneTemplate, reload, }) => { + const { uiMetricService } = useServices(); const decodedTemplateName = decodePath(templateName); const { error, data: templateDetails, isLoading } = loadIndexTemplate(decodedTemplateName); // TS complains if we use destructuring here. Fixed in 3.6.0 (https://github.com/microsoft/TypeScript/pull/31711). diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_list.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_list.tsx similarity index 98% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_list.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_list.tsx index 550fa941e1984..71c32e2e0177f 100644 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_list.tsx +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_list.tsx @@ -20,7 +20,7 @@ import { SectionError, SectionLoading, Error } from '../../../components'; import { TemplateTable } from './template_table'; import { loadIndexTemplates } from '../../../services/api'; import { Template } from '../../../../../common/types'; -import { uiMetricService } from '../../../services/ui_metric'; +import { useServices } from '../../../app_context'; import { getTemplateEditLink, getTemplateListLink, @@ -39,6 +39,7 @@ export const TemplateList: React.FunctionComponent { + const { uiMetricService } = useServices(); const { error, isLoading, data: templates, sendRequest: reload } = loadIndexTemplates(); let content; diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_table/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_table/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_table/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_table/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_table/template_table.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx similarity index 98% rename from x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_table/template_table.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx index 6070b25fb1ca2..72321ccc14888 100644 --- a/x-pack/legacy/plugins/index_management/public/app/sections/home/template_list/template_table/template_table.tsx +++ b/x-pack/legacy/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx @@ -11,7 +11,7 @@ import { EuiInMemoryTable, EuiIcon, EuiButton, EuiLink, EuiBasicTableColumn } fr import { TemplateListItem, Template } from '../../../../../../common/types'; import { BASE_PATH, UIM_TEMPLATE_SHOW_DETAILS_CLICK } from '../../../../../../common/constants'; import { TemplateDeleteModal } from '../../../../components'; -import { uiMetricService } from '../../../../services/ui_metric'; +import { useServices } from '../../../../app_context'; import { getTemplateDetailsLink } from '../../../../services/routing'; import { SendRequestResponse } from '../../../../../shared_imports'; @@ -28,6 +28,7 @@ export const TemplateTable: React.FunctionComponent = ({ editTemplate, cloneTemplate, }) => { + const { uiMetricService } = useServices(); const [selection, setSelection] = useState([]); const [templatesToDelete, setTemplatesToDelete] = useState>([]); diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/template_clone/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/template_clone/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/template_clone/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/template_clone/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/template_clone/template_clone.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/template_clone/template_clone.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/template_clone/template_clone.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/template_clone/template_clone.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/template_create/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/template_create/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/template_create/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/template_create/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/template_create/template_create.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/template_create/template_create.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/template_create/template_create.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/template_create/template_create.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/template_edit/index.ts b/x-pack/legacy/plugins/index_management/public/application/sections/template_edit/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/template_edit/index.ts rename to x-pack/legacy/plugins/index_management/public/application/sections/template_edit/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/sections/template_edit/template_edit.tsx b/x-pack/legacy/plugins/index_management/public/application/sections/template_edit/template_edit.tsx similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/sections/template_edit/template_edit.tsx rename to x-pack/legacy/plugins/index_management/public/application/sections/template_edit/template_edit.tsx diff --git a/x-pack/legacy/plugins/index_management/public/app/services/api.ts b/x-pack/legacy/plugins/index_management/public/application/services/api.ts similarity index 94% rename from x-pack/legacy/plugins/index_management/public/app/services/api.ts rename to x-pack/legacy/plugins/index_management/public/application/services/api.ts index 8030a7f29d4ee..642fd441b353a 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/api.ts +++ b/x-pack/legacy/plugins/index_management/public/application/services/api.ts @@ -34,10 +34,19 @@ import { import { TAB_SETTINGS, TAB_MAPPING, TAB_STATS } from '../constants'; -import { uiMetricService } from './ui_metric'; import { useRequest, sendRequest } from './use_request'; import { httpService } from './http'; +import { UiMetricService } from './ui_metric'; import { Template } from '../../../common/types'; +import { IndexMgmtMetricsType } from '../../types'; + +// Temporary hack to provide the uiMetricService instance to this file. +// TODO: Refactor and export an ApiService instance through the app dependencies context +let uiMetricService: UiMetricService; +export const setUiMetricService = (_uiMetricService: UiMetricService) => { + uiMetricService = _uiMetricService; +}; +// End hack export async function loadIndices() { const response = await httpService.httpClient.get(`${API_BASE_PATH}/indices`); diff --git a/x-pack/legacy/plugins/index_management/public/app/services/breadcrumbs.ts b/x-pack/legacy/plugins/index_management/public/application/services/breadcrumbs.ts similarity index 81% rename from x-pack/legacy/plugins/index_management/public/app/services/breadcrumbs.ts rename to x-pack/legacy/plugins/index_management/public/application/services/breadcrumbs.ts index d35f064a3bcc4..299491756560e 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/breadcrumbs.ts +++ b/x-pack/legacy/plugins/index_management/public/application/services/breadcrumbs.ts @@ -5,26 +5,25 @@ */ import { i18n } from '@kbn/i18n'; import { BASE_PATH } from '../../../common/constants'; -import { ChromeStart } from '../../../../../../../src/core/public'; +import { ManagementAppMountParams } from '../../../../../../../src/plugins/management/public'; + +type SetBreadcrumbs = ManagementAppMountParams['setBreadcrumbs']; class BreadcrumbService { - private chrome: ChromeStart | undefined; private breadcrumbs: { [key: string]: Array<{ text: string; href?: string; }>; } = { - management: [], home: [], }; + private setBreadcrumbsHandler?: SetBreadcrumbs; - public init(chrome: ChromeStart, managementBreadcrumb: any): void { - this.chrome = chrome; - this.breadcrumbs.management = [managementBreadcrumb]; + public setup(setBreadcrumbsHandler: SetBreadcrumbs): void { + this.setBreadcrumbsHandler = setBreadcrumbsHandler; this.breadcrumbs.home = [ - ...this.breadcrumbs.management, { text: i18n.translate('xpack.idxMgmt.breadcrumb.homeLabel', { defaultMessage: 'Index Management', @@ -72,6 +71,10 @@ class BreadcrumbService { } public setBreadcrumbs(type: string): void { + if (!this.setBreadcrumbsHandler) { + throw new Error(`BreadcrumbService#setup() must be called first!`); + } + const newBreadcrumbs = this.breadcrumbs[type] ? [...this.breadcrumbs[type]] : [...this.breadcrumbs.home]; @@ -88,9 +91,7 @@ class BreadcrumbService { href: undefined, }); - if (this.chrome) { - this.chrome.setBreadcrumbs(newBreadcrumbs); - } + this.setBreadcrumbsHandler(newBreadcrumbs); } } diff --git a/x-pack/legacy/plugins/index_management/public/app/services/documentation.ts b/x-pack/legacy/plugins/index_management/public/application/services/documentation.ts similarity index 99% rename from x-pack/legacy/plugins/index_management/public/app/services/documentation.ts rename to x-pack/legacy/plugins/index_management/public/application/services/documentation.ts index 9bf0d983df161..e0f261e586b1e 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/documentation.ts +++ b/x-pack/legacy/plugins/index_management/public/application/services/documentation.ts @@ -12,7 +12,7 @@ class DocumentationService { private esDocsBase: string = ''; private kibanaDocsBase: string = ''; - public init(docLinks: DocLinksStart): void { + public setup(docLinks: DocLinksStart): void { const { DOC_LINK_VERSION, ELASTIC_WEBSITE_URL } = docLinks; const docsBase = `${ELASTIC_WEBSITE_URL}guide/en`; diff --git a/x-pack/legacy/plugins/index_management/public/app/services/health_to_color.ts b/x-pack/legacy/plugins/index_management/public/application/services/health_to_color.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/services/health_to_color.ts rename to x-pack/legacy/plugins/index_management/public/application/services/health_to_color.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/services/http.ts b/x-pack/legacy/plugins/index_management/public/application/services/http.ts similarity index 86% rename from x-pack/legacy/plugins/index_management/public/app/services/http.ts rename to x-pack/legacy/plugins/index_management/public/application/services/http.ts index 34f5abe5983cc..a6973c263f00f 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/http.ts +++ b/x-pack/legacy/plugins/index_management/public/application/services/http.ts @@ -6,10 +6,10 @@ import { HttpSetup } from '../../../../../../../src/core/public'; -class HttpService { +export class HttpService { private client: any; - public init(httpClient: HttpSetup): void { + public setup(httpClient: HttpSetup): void { this.client = httpClient; } diff --git a/x-pack/legacy/plugins/index_management/public/app/services/index.ts b/x-pack/legacy/plugins/index_management/public/application/services/index.ts similarity index 82% rename from x-pack/legacy/plugins/index_management/public/app/services/index.ts rename to x-pack/legacy/plugins/index_management/public/application/services/index.ts index bb5c854e5d96c..78ff8cb5c314a 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/index.ts +++ b/x-pack/legacy/plugins/index_management/public/application/services/index.ts @@ -25,3 +25,7 @@ export { } from './api'; export { healthToColor } from './health_to_color'; export { sortTable } from './sort_table'; + +export { UiMetricService } from './ui_metric'; +export { HttpService } from './http'; +export { NotificationService } from './notification'; diff --git a/x-pack/legacy/plugins/index_management/public/app/services/navigation.ts b/x-pack/legacy/plugins/index_management/public/application/services/navigation.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/services/navigation.ts rename to x-pack/legacy/plugins/index_management/public/application/services/navigation.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/services/notification.ts b/x-pack/legacy/plugins/index_management/public/application/services/notification.ts similarity index 91% rename from x-pack/legacy/plugins/index_management/public/app/services/notification.ts rename to x-pack/legacy/plugins/index_management/public/application/services/notification.ts index 85558a7023491..0971ca77c004b 100644 --- a/x-pack/legacy/plugins/index_management/public/app/services/notification.ts +++ b/x-pack/legacy/plugins/index_management/public/application/services/notification.ts @@ -6,10 +6,10 @@ import { NotificationsStart } from '../../../../../../../src/core/public'; -class NotificationService { +export class NotificationService { private _toasts: any; - public init(notifications: NotificationsStart): void { + public setup(notifications: NotificationsStart): void { this._toasts = notifications.toasts; } diff --git a/x-pack/legacy/plugins/index_management/public/app/services/routing.ts b/x-pack/legacy/plugins/index_management/public/application/services/routing.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/services/routing.ts rename to x-pack/legacy/plugins/index_management/public/application/services/routing.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/services/sort_table.ts b/x-pack/legacy/plugins/index_management/public/application/services/sort_table.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/services/sort_table.ts rename to x-pack/legacy/plugins/index_management/public/application/services/sort_table.ts diff --git a/x-pack/legacy/plugins/index_management/public/application/services/ui_metric.ts b/x-pack/legacy/plugins/index_management/public/application/services/ui_metric.ts new file mode 100644 index 0000000000000..7c87ec9509085 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/services/ui_metric.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { UiStatsMetricType } from '@kbn/analytics'; +import { UsageCollectionSetup } from '../../../../../../../src/plugins/usage_collection/public'; +import { IndexMgmtMetricsType } from '../../types'; + +let uiMetricService: UiMetricService; + +export class UiMetricService { + private appName: string; + private usageCollection: UsageCollectionSetup | undefined; + + constructor(appName: string) { + this.appName = appName; + } + + public setup(usageCollection: UsageCollectionSetup) { + this.usageCollection = usageCollection; + } + + private track(type: T, name: string) { + if (!this.usageCollection) { + throw Error('UiMetricService not initialized.'); + } + this.usageCollection.reportUiStats(this.appName, type as UiStatsMetricType, name); + } + + public trackMetric(type: T, eventName: string) { + return this.track(type, eventName); + } +} + +/** + * To minimize the refactor to migrate to NP where all deps should be explicitely declared + * we will export here the instance created in our plugin.ts setup() so other parts of the code can access it. + * + * TODO: Refactor the api.ts (convert it to a class with setup()) and detail_panel.ts (reducer) to explicitely declare their dependency on the UiMetricService + * @param instance UiMetricService instance from our plugin.ts setup() + */ +export const setUiMetricServiceInstance = (instance: UiMetricService) => { + uiMetricService = instance; +}; + +export const getUiMetricServiceInstance = () => { + return uiMetricService; +}; diff --git a/x-pack/legacy/plugins/index_management/public/app/services/use_request.ts b/x-pack/legacy/plugins/index_management/public/application/services/use_request.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/services/use_request.ts rename to x-pack/legacy/plugins/index_management/public/application/services/use_request.ts diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/clear_cache_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/clear_cache_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/clear_cache_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/clear_cache_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/clear_row_status.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/clear_row_status.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/clear_row_status.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/clear_row_status.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/close_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/close_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/close_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/close_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/delete_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/delete_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/delete_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/delete_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/detail_panel.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/detail_panel.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/detail_panel.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/detail_panel.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/edit_index_settings.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/edit_index_settings.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/edit_index_settings.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/edit_index_settings.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/extension_action.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/extension_action.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/extension_action.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/extension_action.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/flush_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/flush_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/flush_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/flush_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/forcemerge_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/forcemerge_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/forcemerge_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/forcemerge_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/freeze_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/freeze_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/freeze_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/freeze_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/index.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/index.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/index.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/index.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/load_index_data.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/load_index_data.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/load_index_data.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/load_index_data.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/load_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/load_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/load_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/load_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/open_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/open_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/open_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/open_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/refresh_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/refresh_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/refresh_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/refresh_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/reload_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/reload_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/reload_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/reload_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/table_state.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/table_state.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/table_state.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/table_state.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/unfreeze_indices.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/unfreeze_indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/unfreeze_indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/unfreeze_indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/actions/update_index_settings.js b/x-pack/legacy/plugins/index_management/public/application/store/actions/update_index_settings.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/actions/update_index_settings.js rename to x-pack/legacy/plugins/index_management/public/application/store/actions/update_index_settings.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/index.ts b/x-pack/legacy/plugins/index_management/public/application/store/index.ts similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/index.ts rename to x-pack/legacy/plugins/index_management/public/application/store/index.ts diff --git a/x-pack/legacy/plugins/index_management/public/application/store/reducers/detail_panel.js b/x-pack/legacy/plugins/index_management/public/application/store/reducers/detail_panel.js new file mode 100644 index 0000000000000..c38971a633954 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/store/reducers/detail_panel.js @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { handleActions } from 'redux-actions'; +import { + UIM_DETAIL_PANEL_SUMMARY_TAB, + UIM_DETAIL_PANEL_SETTINGS_TAB, + UIM_DETAIL_PANEL_MAPPING_TAB, + UIM_DETAIL_PANEL_STATS_TAB, + UIM_DETAIL_PANEL_EDIT_SETTINGS_TAB, +} from '../../../../common/constants'; +import { + TAB_SUMMARY, + TAB_SETTINGS, + TAB_MAPPING, + TAB_STATS, + TAB_EDIT_SETTINGS, +} from '../../constants'; +import { openDetailPanel, closeDetailPanel } from '../actions/detail_panel'; +import { loadIndexDataSuccess } from '../actions/load_index_data'; +import { + updateIndexSettingsSuccess, + updateIndexSettingsError, +} from '../actions/update_index_settings'; +import { deleteIndicesSuccess } from '../actions/delete_indices'; + +const defaultState = {}; + +export const getDetailPanelReducer = uiMetricService => + handleActions( + { + [deleteIndicesSuccess](state, action) { + const { indexNames } = action.payload; + const { indexName } = state; + if (indexNames.includes(indexName)) { + return {}; + } else { + return state; + } + }, + [openDetailPanel](state, action) { + const { panelType, indexName, title } = action.payload; + + const panelTypeToUiMetricMap = { + [TAB_SUMMARY]: UIM_DETAIL_PANEL_SUMMARY_TAB, + [TAB_SETTINGS]: UIM_DETAIL_PANEL_SETTINGS_TAB, + [TAB_MAPPING]: UIM_DETAIL_PANEL_MAPPING_TAB, + [TAB_STATS]: UIM_DETAIL_PANEL_STATS_TAB, + [TAB_EDIT_SETTINGS]: UIM_DETAIL_PANEL_EDIT_SETTINGS_TAB, + }; + + if (panelTypeToUiMetricMap[panelType]) { + uiMetricService.trackMetric('count', panelTypeToUiMetricMap[panelType]); + } + + return { + panelType: panelType || state.panelType || TAB_SUMMARY, + indexName, + title, + }; + }, + [closeDetailPanel]() { + return {}; + }, + [loadIndexDataSuccess](state, action) { + const { data } = action.payload; + const newState = { + ...state, + data, + }; + return newState; + }, + [updateIndexSettingsError](state, action) { + const { error } = action.payload; + const newState = { + ...state, + error, + }; + return newState; + }, + [updateIndexSettingsSuccess]() { + return {}; + }, + }, + defaultState + ); diff --git a/x-pack/legacy/plugins/index_management/public/app/store/store.d.ts b/x-pack/legacy/plugins/index_management/public/application/store/reducers/index.js similarity index 82% rename from x-pack/legacy/plugins/index_management/public/app/store/store.d.ts rename to x-pack/legacy/plugins/index_management/public/application/store/reducers/index.js index 4772f2124bfe0..ff2b94b0d36e9 100644 --- a/x-pack/legacy/plugins/index_management/public/app/store/store.d.ts +++ b/x-pack/legacy/plugins/index_management/public/application/store/reducers/index.js @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export declare function indexManagementStore(): any; +export { getReducer } from './index_management'; diff --git a/x-pack/legacy/plugins/index_management/public/app/store/reducers/index_management.js b/x-pack/legacy/plugins/index_management/public/application/store/reducers/index_management.js similarity index 63% rename from x-pack/legacy/plugins/index_management/public/app/store/reducers/index_management.js rename to x-pack/legacy/plugins/index_management/public/application/store/reducers/index_management.js index 14f270670c0d6..233e6f692ca70 100644 --- a/x-pack/legacy/plugins/index_management/public/app/store/reducers/index_management.js +++ b/x-pack/legacy/plugins/index_management/public/application/store/reducers/index_management.js @@ -5,14 +5,15 @@ */ import { combineReducers } from 'redux'; -import { detailPanel } from './detail_panel'; +import { getDetailPanelReducer } from './detail_panel'; import { indices } from './indices'; import { rowStatus } from './row_status'; import { tableState } from './table_state'; -export const indexManagement = combineReducers({ - indices, - rowStatus, - tableState, - detailPanel, -}); +export const getReducer = ({ uiMetricService }) => + combineReducers({ + indices, + rowStatus, + tableState, + detailPanel: getDetailPanelReducer(uiMetricService), + }); diff --git a/x-pack/legacy/plugins/index_management/public/app/store/reducers/indices.js b/x-pack/legacy/plugins/index_management/public/application/store/reducers/indices.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/reducers/indices.js rename to x-pack/legacy/plugins/index_management/public/application/store/reducers/indices.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/reducers/row_status.js b/x-pack/legacy/plugins/index_management/public/application/store/reducers/row_status.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/reducers/row_status.js rename to x-pack/legacy/plugins/index_management/public/application/store/reducers/row_status.js diff --git a/x-pack/legacy/plugins/index_management/public/app/store/reducers/table_state.js b/x-pack/legacy/plugins/index_management/public/application/store/reducers/table_state.js similarity index 100% rename from x-pack/legacy/plugins/index_management/public/app/store/reducers/table_state.js rename to x-pack/legacy/plugins/index_management/public/application/store/reducers/table_state.js diff --git a/x-pack/legacy/plugins/index_management/public/application/store/selectors/index.d.ts b/x-pack/legacy/plugins/index_management/public/application/store/selectors/index.d.ts new file mode 100644 index 0000000000000..999b11c5d6665 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/store/selectors/index.d.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { ExtensionsService } from '../../../services'; + +export declare function setExtensionsService(extensionsService: ExtensionsService): any; diff --git a/x-pack/legacy/plugins/index_management/public/app/store/selectors/index.js b/x-pack/legacy/plugins/index_management/public/application/store/selectors/index.js similarity index 93% rename from x-pack/legacy/plugins/index_management/public/app/store/selectors/index.js rename to x-pack/legacy/plugins/index_management/public/application/store/selectors/index.js index 654e7276bbb08..3ddbf28651fa0 100644 --- a/x-pack/legacy/plugins/index_management/public/app/store/selectors/index.js +++ b/x-pack/legacy/plugins/index_management/public/application/store/selectors/index.js @@ -8,7 +8,15 @@ import { Pager, EuiSearchBar } from '@elastic/eui'; import { createSelector } from 'reselect'; import { indexStatusLabels } from '../../lib/index_status_labels'; import { sortTable } from '../../services'; -import { getToggleExtensions } from '../../../index_management_extensions'; + +// Temporary hack to provide the extensionsService instance to this file. +// TODO: Refactor and export all the app selectors through the app dependencies context + +let extensionsService; +export const setExtensionsService = _extensionsService => { + extensionsService = _extensionsService; +}; +// End hack export const getDetailPanelData = state => state.detailPanel.data; export const getDetailPanelError = state => state.detailPanel.error; @@ -46,7 +54,7 @@ export const hasSystemIndex = indexNames => { const defaultFilterFields = ['name']; const filterByToggles = (indices, toggleNameToVisibleMap) => { - const togglesByName = getToggleExtensions().reduce( + const togglesByName = extensionsService.toggles.reduce( (byName, toggle) => ({ ...byName, [toggle.name]: toggle, diff --git a/x-pack/legacy/plugins/index_management/public/application/store/store.d.ts b/x-pack/legacy/plugins/index_management/public/application/store/store.d.ts new file mode 100644 index 0000000000000..1568275badeee --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/application/store/store.d.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { AppDependencies } from '../app_context'; + +export declare function indexManagementStore(services: AppDependencies['services']): any; diff --git a/x-pack/legacy/plugins/index_management/public/app/store/store.js b/x-pack/legacy/plugins/index_management/public/application/store/store.js similarity index 71% rename from x-pack/legacy/plugins/index_management/public/app/store/store.js rename to x-pack/legacy/plugins/index_management/public/application/store/store.js index 3e80274a96960..e103ff0778be1 100644 --- a/x-pack/legacy/plugins/index_management/public/app/store/store.js +++ b/x-pack/legacy/plugins/index_management/public/application/store/store.js @@ -6,19 +6,18 @@ import { createStore, applyMiddleware, compose } from 'redux'; import thunk from 'redux-thunk'; -import { getToggleExtensions } from '../../index_management_extensions'; import { defaultTableState } from './reducers/table_state'; -import { indexManagement } from './reducers/'; +import { getReducer } from './reducers/'; -export function indexManagementStore() { +export function indexManagementStore(services) { const toggleNameToVisibleMap = {}; - getToggleExtensions().forEach(toggleExtension => { + services.extensionsService.toggles.forEach(toggleExtension => { toggleNameToVisibleMap[toggleExtension.name] = false; }); const initialState = { tableState: { ...defaultTableState, toggleNameToVisibleMap } }; const enhancers = [applyMiddleware(thunk)]; window.__REDUX_DEVTOOLS_EXTENSION__ && enhancers.push(window.__REDUX_DEVTOOLS_EXTENSION__()); - return createStore(indexManagement, initialState, compose(...enhancers)); + return createStore(getReducer(services), initialState, compose(...enhancers)); } diff --git a/x-pack/legacy/plugins/index_management/public/index.scss b/x-pack/legacy/plugins/index_management/public/index.scss index 7128e4a207ca1..0fbf8ea5036c5 100644 --- a/x-pack/legacy/plugins/index_management/public/index.scss +++ b/x-pack/legacy/plugins/index_management/public/index.scss @@ -10,7 +10,7 @@ // indChart__legend--small // indChart__legend-isLoading -@import './app/components/mappings_editor/index'; +@import './application/components/mappings_editor/index'; .indTable { // The index table is a bespoke table and can't make use of EuiBasicTable's width settings diff --git a/x-pack/legacy/plugins/index_management/public/index.ts b/x-pack/legacy/plugins/index_management/public/index.ts index 3003c4e909956..16e7bf21aee98 100644 --- a/x-pack/legacy/plugins/index_management/public/index.ts +++ b/x-pack/legacy/plugins/index_management/public/index.ts @@ -3,43 +3,19 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { npStart } from 'ui/new_platform'; +import { npSetup } from 'ui/new_platform'; -import { IndexMgmtPlugin } from './plugin'; -import { __LEGACYStart } from './legacy'; -import { - addSummaryExtension, - getSummaryExtensions, - addActionExtension, - getActionExtensions, - addBannerExtension, - getBannerExtensions, - addFilterExtension, - getFilterExtensions, - addToggleExtension, - getToggleExtensions, - addBadgeExtension, - getBadgeExtensions, -} from './index_management_extensions'; +import { IndexMgmtUIPlugin, IndexMgmtSetup } from './plugin'; + +/** @public */ +export { IndexMgmtSetup }; export const plugin = () => { - return new IndexMgmtPlugin(); + return new IndexMgmtUIPlugin(); }; -/** @public */ -export { - addSummaryExtension, - getSummaryExtensions, - addActionExtension, - getActionExtensions, - addBannerExtension, - getBannerExtensions, - addFilterExtension, - getFilterExtensions, - addToggleExtension, - getToggleExtensions, - addBadgeExtension, - getBadgeExtensions, -}; +// Temp. To be removed after moving to the "plugins" folder + +const { extensionsService } = plugin().setup(npSetup.core, npSetup.plugins); -plugin().start(npStart.core, npStart.plugins, __LEGACYStart); +export { extensionsService }; diff --git a/x-pack/legacy/plugins/index_management/public/index_management_extensions.ts b/x-pack/legacy/plugins/index_management/public/index_management_extensions.ts deleted file mode 100644 index 2f578e7c4a5a4..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/index_management_extensions.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { i18n } from '@kbn/i18n'; - -const summaryExtensions: any[] = []; -export const addSummaryExtension = (summaryExtension: any) => { - summaryExtensions.push(summaryExtension); -}; - -export const getSummaryExtensions = () => { - return summaryExtensions; -}; - -const actionExtensions: any[] = []; -export const addActionExtension = (actionExtension: any) => { - actionExtensions.push(actionExtension); -}; - -export const getActionExtensions = () => { - return actionExtensions; -}; - -const bannerExtensions: any[] = []; -export const addBannerExtension = (actionExtension: any) => { - bannerExtensions.push(actionExtension); -}; - -export const getBannerExtensions = () => { - return bannerExtensions; -}; - -const filterExtensions: any[] = []; -export const addFilterExtension = (filterExtension: any) => { - filterExtensions.push(filterExtension); -}; - -export const getFilterExtensions = () => { - return filterExtensions; -}; - -const toggleExtensions: any[] = []; -export const addToggleExtension = (toggleExtension: any) => { - toggleExtensions.push(toggleExtension); -}; - -export const getToggleExtensions = () => { - return toggleExtensions; -}; - -const badgeExtensions = [ - { - matchIndex: (index: { isFrozen: boolean }) => { - return index.isFrozen; - }, - label: i18n.translate('xpack.idxMgmt.frozenBadgeLabel', { - defaultMessage: 'Frozen', - }), - filterExpression: 'isFrozen:true', - color: 'primary', - }, -]; - -export const addBadgeExtension = (badgeExtension: any) => { - badgeExtensions.push(badgeExtension); -}; - -export const getBadgeExtensions = () => { - return badgeExtensions; -}; diff --git a/x-pack/legacy/plugins/index_management/public/legacy.ts b/x-pack/legacy/plugins/index_management/public/legacy.ts deleted file mode 100644 index eee24feff5a67..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/legacy.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { management, MANAGEMENT_BREADCRUMB } from 'ui/management'; -import { createUiStatsReporter } from '../../../../../src/legacy/core_plugins/ui_metric/public'; - -export interface LegacyStart { - management: { - getSection: typeof management.getSection; - constants: { - BREADCRUMB: typeof MANAGEMENT_BREADCRUMB; - }; - }; - uiMetric: { - createUiStatsReporter: typeof createUiStatsReporter; - }; -} - -export const __LEGACYStart = { - management: { - getSection: management.getSection.bind(management), - constants: { - BREADCRUMB: MANAGEMENT_BREADCRUMB, - }, - }, - uiMetric: { - createUiStatsReporter, - }, -}; diff --git a/x-pack/legacy/plugins/index_management/public/mocks.ts b/x-pack/legacy/plugins/index_management/public/mocks.ts new file mode 100644 index 0000000000000..7062e7bacace0 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/mocks.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { extensionsServiceMock } from './services/extensions_service.mock'; + +export { extensionsServiceMock } from './services/extensions_service.mock'; + +function createIdxManagementSetupMock() { + const mock = { + extensionsService: extensionsServiceMock, + }; + + return mock; +} + +export const indexManagementMock = { + createSetup: createIdxManagementSetupMock, +}; diff --git a/x-pack/legacy/plugins/index_management/public/plugin.ts b/x-pack/legacy/plugins/index_management/public/plugin.ts index 71ecdd7a1fbef..539324766cf95 100644 --- a/x-pack/legacy/plugins/index_management/public/plugin.ts +++ b/x-pack/legacy/plugins/index_management/public/plugin.ts @@ -3,32 +3,90 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { CoreStart } from '../../../../../src/core/public'; - -import { registerManagementSection } from './register_management_section'; -import { registerRoutes } from './register_routes'; -import { LegacyStart } from './legacy'; - -import { httpService } from './app/services/http'; -import { breadcrumbService } from './app/services/breadcrumbs'; -import { documentationService } from './app/services/documentation'; -import { notificationService } from './app/services/notification'; -import { uiMetricService } from './app/services/ui_metric'; - -export class IndexMgmtPlugin { - public start(core: CoreStart, plugins: {}, __LEGACY: LegacyStart) { - const { management, uiMetric } = __LEGACY; - const { http, chrome, docLinks, notifications } = core; - - // Initialize services - httpService.init(http); - breadcrumbService.init(chrome, management.constants.BREADCRUMB); - documentationService.init(docLinks); - notificationService.init(notifications); - uiMetricService.init(uiMetric.createUiStatsReporter); - - // Register management section and Angular route - registerManagementSection(management.getSection('elasticsearch')); - registerRoutes(core); +import { i18n } from '@kbn/i18n'; + +import { CoreSetup } from '../../../../../src/core/public'; +import { UsageCollectionSetup } from '../../../../../src/plugins/usage_collection/public'; +import { ManagementSetup } from '../../../../../src/plugins/management/public'; +import { UIM_APP_NAME } from '../common/constants'; + +import { AppDependencies } from './application'; +import { httpService } from './application/services/http'; +import { breadcrumbService } from './application/services/breadcrumbs'; +import { documentationService } from './application/services/documentation'; +import { notificationService } from './application/services/notification'; +import { UiMetricService } from './application/services/ui_metric'; + +import { setExtensionsService } from './application/store/selectors'; +import { setUiMetricService } from './application/services/api'; + +import { IndexMgmtMetricsType } from './types'; +import { ExtensionsService, ExtensionsSetup } from './services'; + +export interface IndexMgmtSetup { + extensionsService: ExtensionsSetup; +} + +interface PluginsDependencies { + usageCollection: UsageCollectionSetup; + management: ManagementSetup; +} + +export class IndexMgmtUIPlugin { + private uiMetricService = new UiMetricService(UIM_APP_NAME); + private extensionsService = new ExtensionsService(); + + constructor() { + // Temporary hack to provide the service instances in module files in order to avoid a big refactor + // For the selectors we should expose them through app dependencies and read them from there on each container component. + setExtensionsService(this.extensionsService); + setUiMetricService(this.uiMetricService); } + + public setup(coreSetup: CoreSetup, plugins: PluginsDependencies): IndexMgmtSetup { + const { http, notifications, getStartServices } = coreSetup; + const { usageCollection, management } = plugins; + + httpService.setup(http); + notificationService.setup(notifications); + this.uiMetricService.setup(usageCollection); + + management.sections.getSection('elasticsearch')!.registerApp({ + id: 'index_management', + title: i18n.translate('xpack.idxMgmt.appTitle', { defaultMessage: 'Index Management' }), + order: 1, + mount: async ({ element, setBreadcrumbs }) => { + const [core] = await getStartServices(); + const { docLinks, fatalErrors } = core; + + breadcrumbService.setup(setBreadcrumbs); + documentationService.setup(docLinks); + + const appDependencies: AppDependencies = { + core: { + fatalErrors, + }, + plugins: { + usageCollection, + }, + services: { + uiMetricService: this.uiMetricService, + extensionsService: this.extensionsService, + httpService, + notificationService, + }, + }; + + const { renderApp } = await import('./application'); + return renderApp(element, { core, dependencies: appDependencies }); + }, + }); + + return { + extensionsService: this.extensionsService.setup(), + }; + } + + public start() {} + public stop() {} } diff --git a/x-pack/legacy/plugins/index_management/public/register_management_section.ts b/x-pack/legacy/plugins/index_management/public/register_management_section.ts deleted file mode 100644 index f090b322583d2..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/register_management_section.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import { BASE_PATH } from '../common/constants'; - -export const registerManagementSection = (esSection: { - register: (section: string, config: {}) => void; -}) => { - esSection.register('index_management', { - visible: true, - display: i18n.translate('xpack.idxMgmt.appTitle', { defaultMessage: 'Index Management' }), - order: 1, - url: `#${BASE_PATH}indices`, - }); -}; diff --git a/x-pack/legacy/plugins/index_management/public/register_routes.ts b/x-pack/legacy/plugins/index_management/public/register_routes.ts deleted file mode 100644 index 378a53cf65555..0000000000000 --- a/x-pack/legacy/plugins/index_management/public/register_routes.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import routes from 'ui/routes'; - -import { CoreStart } from '../../../../../src/core/public'; - -import { mountReactApp, unmountReactApp } from './app'; -import { REACT_ROOT_ID } from './app/constants'; -import { BASE_PATH } from '../common/constants'; - -import template from './index.html'; -import { manageAngularLifecycle } from './app/lib/manage_angular_lifecycle'; - -let elem: HTMLElement | null; - -export const registerRoutes = (core: CoreStart) => { - routes.when(`${BASE_PATH}:view?/:action?/:id?`, { - template, - controller: ($scope: any, $route: any) => { - // clean up previously rendered React app if one exists - // this happens because of React Router redirects - unmountReactApp(elem); - - $scope.$$postDigest(() => { - elem = document.getElementById(REACT_ROOT_ID); - mountReactApp(elem, { core }); - manageAngularLifecycle($scope, $route, elem); - }); - }, - }); -}; diff --git a/x-pack/legacy/plugins/index_management/public/services/extensions_service.mock.ts b/x-pack/legacy/plugins/index_management/public/services/extensions_service.mock.ts new file mode 100644 index 0000000000000..3075a114eedd1 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/services/extensions_service.mock.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ExtensionsService, ExtensionsSetup } from './extensions_service'; + +export type ExtensionsSetupMock = jest.Mocked; + +const createServiceMock = (): ExtensionsSetupMock => ({ + addAction: jest.fn(), + addBadge: jest.fn(), + addBanner: jest.fn(), + addFilter: jest.fn(), + addSummary: jest.fn(), + addToggle: jest.fn(), +}); + +const createMock = () => { + const mocked: jest.Mocked> = { + setup: jest.fn(), + }; + mocked.setup.mockReturnValue(createServiceMock()); + return mocked; +}; + +export const extensionsServiceMock = { + create: createMock, + createSetupContract: createServiceMock, +}; diff --git a/x-pack/legacy/plugins/index_management/public/services/extensions_service.ts b/x-pack/legacy/plugins/index_management/public/services/extensions_service.ts new file mode 100644 index 0000000000000..22e0546beff99 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/services/extensions_service.ts @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { i18n } from '@kbn/i18n'; + +export interface ExtensionsSetup { + addSummary(summary: any): void; + addAction(action: any): void; + addBanner(banner: any): void; + addFilter(filter: any): void; + addBadge(badge: any): void; + addToggle(toggle: any): void; +} + +export class ExtensionsService { + private _summaries: any[] = []; + private _actions: any[] = []; + private _banners: any[] = []; + private _filters: any[] = []; + private _badges: any[] = [ + { + matchIndex: (index: { isFrozen: boolean }) => { + return index.isFrozen; + }, + label: i18n.translate('xpack.idxMgmt.frozenBadgeLabel', { + defaultMessage: 'Frozen', + }), + filterExpression: 'isFrozen:true', + color: 'primary', + }, + ]; + private _toggles: any[] = []; + private service?: ExtensionsSetup; + + public setup(): ExtensionsSetup { + this.service = { + addAction: this.addAction.bind(this), + addBadge: this.addBadge.bind(this), + addBanner: this.addBanner.bind(this), + addFilter: this.addFilter.bind(this), + addSummary: this.addSummary.bind(this), + addToggle: this.addToggle.bind(this), + }; + + return this.service; + } + + private addSummary(summary: any) { + this._summaries.push(summary); + } + + private addAction(action: any) { + this._actions.push(action); + } + + private addBanner(banner: any) { + this._banners.push(banner); + } + + private addFilter(filter: any) { + this._filters.push(filter); + } + + private addBadge(badge: any) { + this._badges.push(badge); + } + + private addToggle(toggle: any) { + this._toggles.push(toggle); + } + + public get summaries() { + return this._summaries; + } + + public get actions() { + return this._actions; + } + + public get banners() { + return this._banners; + } + + public get filters() { + return this._filters; + } + + public get badges() { + return this._badges; + } + + public get toggles() { + return this._toggles; + } +} diff --git a/x-pack/legacy/plugins/index_management/public/services/index.ts b/x-pack/legacy/plugins/index_management/public/services/index.ts new file mode 100644 index 0000000000000..e5dfabe1d1190 --- /dev/null +++ b/x-pack/legacy/plugins/index_management/public/services/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { ExtensionsService, ExtensionsSetup } from './extensions_service'; diff --git a/x-pack/legacy/plugins/index_management/public/app/store/reducers/index.js b/x-pack/legacy/plugins/index_management/public/types.ts similarity index 78% rename from x-pack/legacy/plugins/index_management/public/app/store/reducers/index.js rename to x-pack/legacy/plugins/index_management/public/types.ts index eeae581be9473..08fbf63450218 100644 --- a/x-pack/legacy/plugins/index_management/public/app/store/reducers/index.js +++ b/x-pack/legacy/plugins/index_management/public/types.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { indexManagement } from './index_management'; +export type IndexMgmtMetricsType = 'loaded' | 'click' | 'count'; diff --git a/x-pack/legacy/plugins/rollup/public/legacy.ts b/x-pack/legacy/plugins/rollup/public/legacy.ts index 17597672a898e..64eb1f6436389 100644 --- a/x-pack/legacy/plugins/rollup/public/legacy.ts +++ b/x-pack/legacy/plugins/rollup/public/legacy.ts @@ -10,7 +10,7 @@ import { aggTypeFieldFilters } from 'ui/agg_types'; import { addSearchStrategy } from '../../../../../src/plugins/data/public'; import { RollupPlugin } from './plugin'; import { setup as management } from '../../../../../src/legacy/core_plugins/management/public/legacy'; -import { addBadgeExtension, addToggleExtension } from '../../index_management/public'; +import { extensionsService } from '../../index_management/public'; const plugin = new RollupPlugin(); @@ -20,8 +20,7 @@ export const setup = plugin.setup(npSetup.core, { aggTypeFilters, aggTypeFieldFilters, addSearchStrategy, - addBadgeExtension, - addToggleExtension, + indexManagementExtensions: extensionsService, managementLegacy: management, }, }); diff --git a/x-pack/legacy/plugins/rollup/public/plugin.ts b/x-pack/legacy/plugins/rollup/public/plugin.ts index 4dae078c90f57..90d7e2d9d0191 100644 --- a/x-pack/legacy/plugins/rollup/public/plugin.ts +++ b/x-pack/legacy/plugins/rollup/public/plugin.ts @@ -27,6 +27,7 @@ import { // @ts-ignore import { CRUD_APP_BASE_PATH } from './crud_app/constants'; import { ManagementSetup } from '../../../../../src/plugins/management/public'; +import { IndexMgmtSetup } from '../../index_management/public'; // @ts-ignore import { setEsBaseAndXPackBase, setHttp } from './crud_app/services'; import { setNotifications, setFatalErrors } from './kibana_services'; @@ -38,8 +39,7 @@ export interface RollupPluginSetupDependencies { aggTypeFieldFilters: AggTypeFieldFilters; addSearchStrategy: (searchStrategy: SearchStrategyProvider) => void; managementLegacy: ManagementSetupLegacy; - addBadgeExtension: (badgeExtension: any) => void; - addToggleExtension: (toggleExtension: any) => void; + indexManagementExtensions: IndexMgmtSetup['extensionsService']; }; home?: HomePublicPluginSetup; management: ManagementSetup; @@ -54,16 +54,15 @@ export class RollupPlugin implements Plugin { aggTypeFieldFilters, addSearchStrategy, managementLegacy, - addBadgeExtension, - addToggleExtension, + indexManagementExtensions, }, home, management, }: RollupPluginSetupDependencies ) { setFatalErrors(core.fatalErrors); - addBadgeExtension(rollupBadgeExtension); - addToggleExtension(rollupToggleExtension); + indexManagementExtensions.addBadge(rollupBadgeExtension); + indexManagementExtensions.addToggle(rollupToggleExtension); const isRollupIndexPatternsEnabled = core.uiSettings.get(CONFIG_ROLLUPS); From f4d29abf1cd8763396bb9fbb1e19df73f31132c8 Mon Sep 17 00:00:00 2001 From: patrykkopycinski Date: Mon, 17 Feb 2020 09:58:54 +0100 Subject: [PATCH 04/21] Bump redux dependencies (#53348) --- package.json | 31 +- packages/kbn-pm/dist/index.js | 5298 +++++++---------- .../public/utils/typed_react.ts | 47 - .../workpad_app/workpad_telemetry.test.tsx | 13 +- .../workpad/workpad_app/workpad_telemetry.tsx | 37 +- .../canvas/public/components/router/router.js | 6 +- .../sidebar/element_settings/index.tsx | 5 - .../field_manager/field_manager.test.tsx | 4 +- .../field_manager/field_manager.tsx | 2 + .../components/logging/log_time_controls.tsx | 2 +- .../waffle/waffle_time_controls.tsx | 5 +- .../infra/public/utils/redux_context.tsx | 10 +- .../infra/public/utils/typed_react.tsx | 13 +- .../layer_addpanel/index.js | 2 +- .../connected_components/map/mb/index.js | 2 +- .../layer_control/layer_toc/index.js | 2 +- .../population_view/metric_selection.tsx | 5 +- .../jobs/new_job/pages/new_job/wizard.tsx | 10 +- .../drag_drop_context_wrapper.tsx | 11 +- .../drag_and_drop/draggable_wrapper.tsx | 24 +- .../error_toast_dispatcher/index.tsx | 25 +- .../public/components/events_viewer/index.tsx | 67 +- .../components/fields_browser/index.test.tsx | 29 + .../components/fields_browser/index.tsx | 27 +- .../public/components/flyout/header/index.tsx | 91 +- .../siem/public/components/flyout/index.tsx | 44 +- .../public/components/flyout/pane/index.tsx | 25 +- .../components/open_timeline/helpers.ts | 10 +- .../public/components/open_timeline/index.tsx | 16 +- .../public/components/open_timeline/types.ts | 17 - .../hosts/authentications_table/index.tsx | 35 +- .../page/hosts/hosts_table/index.tsx | 39 +- .../hosts/uncommon_process_table/index.tsx | 35 +- .../page/network/network_dns_table/index.tsx | 30 +- .../__snapshots__/index.test.tsx.snap | 2 +- .../network/network_http_table/index.test.tsx | 2 +- .../page/network/network_http_table/index.tsx | 201 +- .../network_top_countries_table/index.tsx | 36 +- .../network_top_n_flow_table/index.tsx | 36 +- .../page/network/tls_table/index.tsx | 34 +- .../page/network/users_table/index.tsx | 29 +- .../components/recent_timelines/index.tsx | 20 +- .../public/components/search_bar/index.tsx | 43 +- .../components/super_date_picker/index.tsx | 41 +- .../timeline/auto_save_warning/index.tsx | 38 +- .../components/timeline/body/index.test.tsx | 6 - .../public/components/timeline/body/index.tsx | 1 - .../timeline/body/stateful_body.tsx | 74 +- .../timeline/fetch_kql_timeline.tsx | 32 +- .../siem/public/components/timeline/index.tsx | 128 +- .../components/timeline/refetch_timeline.tsx | 32 +- .../timeline/search_or_filter/index.tsx | 64 +- .../public/components/timeline/timeline.tsx | 2 +- .../public/containers/global_time/index.tsx | 30 +- .../public/containers/ip_overview/index.tsx | 14 +- .../containers/kpi_host_details/index.tsx | 14 +- .../public/containers/kpi_hosts/index.tsx | 14 +- .../public/containers/kpi_network/index.tsx | 14 +- .../overview/overview_host/index.tsx | 14 +- .../overview/overview_network/index.tsx | 74 +- .../siem/public/containers/timeline/index.tsx | 15 +- .../containers/uncommon_processes/index.tsx | 16 +- .../siem/public/containers/users/index.tsx | 25 +- .../components/signals/index.tsx | 45 +- .../detection_engine/detection_engine.tsx | 33 +- .../detection_engine/rules/details/index.tsx | 32 +- .../plugins/siem/public/pages/home/index.tsx | 4 +- .../pages/hosts/details/details_tabs.tsx | 4 +- .../siem/public/pages/hosts/details/index.tsx | 25 +- .../siem/public/pages/hosts/hosts.test.tsx | 9 - .../plugins/siem/public/pages/hosts/hosts.tsx | 27 +- .../plugins/siem/public/pages/hosts/index.tsx | 8 +- .../plugins/siem/public/pages/hosts/types.ts | 28 +- .../pages/network/ip_details/index.test.tsx | 2 +- .../public/pages/network/ip_details/index.tsx | 19 +- .../public/pages/network/ip_details/types.ts | 26 +- .../siem/public/pages/network/network.tsx | 14 +- .../siem/public/pages/network/types.ts | 14 +- .../siem/public/pages/overview/overview.tsx | 22 +- .../siem/public/store/inputs/actions.ts | 4 +- .../siem/public/store/inputs/helpers.ts | 4 +- .../siem/public/store/network/selectors.ts | 9 +- .../functional/charts/ping_histogram.tsx | 2 +- .../contexts/uptime_refresh_context.tsx | 1 + .../plugins/uptime/public/uptime_app.tsx | 1 + x-pack/package.json | 37 +- yarn.lock | 481 +- 87 files changed, 2967 insertions(+), 4954 deletions(-) diff --git a/package.json b/package.json index e801f75b976f8..e4fdaf32a014a 100644 --- a/package.json +++ b/package.json @@ -80,12 +80,14 @@ }, "resolutions": { "**/@types/node": "10.12.27", - "**/@types/react": "^16.9.13", + "**/@types/react": "^16.9.19", "**/@types/react-router": "^5.1.3", "**/@types/hapi": "^17.0.18", "**/@types/angular": "^1.6.56", + "**/@types/hoist-non-react-statics": "^3.3.1", "**/typescript": "3.7.2", "**/graphql-toolkit/lodash": "^4.17.13", + "**/hoist-non-react-statics": "^3.3.2", "**/isomorphic-git/**/base64-js": "^1.2.1", "**/image-diff/gm/debug": "^2.6.9", "**/react-dom": "^16.12.0", @@ -234,19 +236,19 @@ "react-input-range": "^1.3.0", "react-markdown": "^3.4.1", "react-monaco-editor": "~0.27.0", - "react-redux": "^5.1.2", + "react-redux": "^7.1.3", "react-resize-detector": "^4.2.0", "react-router-dom": "^5.1.2", "react-sizeme": "^2.3.6", "react-use": "^13.13.0", "reactcss": "1.2.3", - "redux": "4.0.0", - "redux-actions": "2.6.5", - "redux-thunk": "2.3.0", + "redux": "^4.0.5", + "redux-actions": "^2.6.5", + "redux-thunk": "^2.3.0", "regenerator-runtime": "^0.13.3", "regression": "2.0.1", "request": "^2.88.0", - "reselect": "^3.0.1", + "reselect": "^4.0.0", "resize-observer-polyfill": "^1.5.0", "rison-node": "1.0.2", "rxjs": "^6.5.3", @@ -318,7 +320,7 @@ "@types/deep-freeze-strict": "^1.1.0", "@types/delete-empty": "^2.0.0", "@types/elasticsearch": "^5.0.33", - "@types/enzyme": "^3.9.0", + "@types/enzyme": "^3.10.5", "@types/eslint": "^6.1.3", "@types/fetch-mock": "^7.3.1", "@types/flot": "^0.0.31", @@ -356,16 +358,15 @@ "@types/podium": "^1.0.0", "@types/prop-types": "^15.5.3", "@types/reach__router": "^1.2.6", - "@types/react": "^16.9.11", - "@types/react-dom": "^16.9.4", + "@types/react": "^16.9.19", + "@types/react-dom": "^16.9.5", "@types/react-grid-layout": "^0.16.7", - "@types/react-redux": "^6.0.6", + "@types/react-redux": "^7.1.7", "@types/react-resize-detector": "^4.0.1", "@types/react-router": "^5.1.3", "@types/react-router-dom": "^5.1.3", "@types/react-virtualized": "^9.18.7", "@types/recompose": "^0.30.6", - "@types/redux": "^3.6.31", "@types/redux-actions": "^2.6.1", "@types/request": "^2.48.2", "@types/selenium-webdriver": "^4.0.5", @@ -398,10 +399,10 @@ "classnames": "2.2.6", "dedent": "^0.7.0", "delete-empty": "^2.0.0", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.15.1", - "enzyme-adapter-utils": "^1.12.1", - "enzyme-to-json": "^3.4.3", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.2", + "enzyme-adapter-utils": "^1.13.0", + "enzyme-to-json": "^3.4.4", "eslint": "^6.8.0", "eslint-config-prettier": "^6.9.0", "eslint-plugin-babel": "^5.3.0", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 314bcf31e6d05..2ccff3e9c3df2 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -94,7 +94,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; }); -/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(705); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(704); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildProductionProjects"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); @@ -105,10 +105,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_project__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(516); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Project", function() { return _utils_project__WEBPACK_IMPORTED_MODULE_3__["Project"]; }); -/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(579); +/* harmony import */ var _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(578); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "copyWorkspacePackages", function() { return _utils_workspaces__WEBPACK_IMPORTED_MODULE_4__["copyWorkspacePackages"]; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(580); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(579); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; }); /* @@ -152,7 +152,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(690); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(689); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(34); /* * Licensed to Elasticsearch B.V. under one or more contributor @@ -2506,9 +2506,9 @@ module.exports = require("path"); __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; }); /* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18); -/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(587); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(687); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(688); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(586); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(686); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(687); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -2551,8 +2551,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34); /* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(500); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(501); -/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(581); -/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(586); +/* harmony import */ var _utils_project_checksums__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(580); +/* harmony import */ var _utils_bootstrap_cache_file__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(585); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -44027,7 +44027,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(515); /* harmony import */ var _project__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(516); -/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(579); +/* harmony import */ var _workspaces__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(578); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -47547,7 +47547,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(515); /* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); /* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(517); -/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(564); +/* harmony import */ var _scripts__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(563); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -48399,33 +48399,38 @@ function bugsTypos(bugs, warn) { /* 522 */ /***/ (function(module, exports) { -exports = module.exports = SemVer; - -// The debug function is excluded entirely from the minified version. -/* nomin */ var debug; -/* nomin */ if (typeof process === 'object' && - /* nomin */ process.env && - /* nomin */ process.env.NODE_DEBUG && - /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) - /* nomin */ debug = function() { - /* nomin */ var args = Array.prototype.slice.call(arguments, 0); - /* nomin */ args.unshift('SEMVER'); - /* nomin */ console.log.apply(console, args); - /* nomin */ }; -/* nomin */ else - /* nomin */ debug = function() {}; +exports = module.exports = SemVer + +var debug +/* istanbul ignore next */ +if (typeof process === 'object' && + process.env && + process.env.NODE_DEBUG && + /\bsemver\b/i.test(process.env.NODE_DEBUG)) { + debug = function () { + var args = Array.prototype.slice.call(arguments, 0) + args.unshift('SEMVER') + console.log.apply(console, args) + } +} else { + debug = function () {} +} // Note: this is the semver.org version of the spec that it implements // Not necessarily the package version of this code. -exports.SEMVER_SPEC_VERSION = '2.0.0'; +exports.SEMVER_SPEC_VERSION = '2.0.0' + +var MAX_LENGTH = 256 +var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || + /* istanbul ignore next */ 9007199254740991 -var MAX_LENGTH = 256; -var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; +// Max safe segment length for coercion. +var MAX_SAFE_COMPONENT_LENGTH = 16 // The actual regexps go on exports.re -var re = exports.re = []; -var src = exports.src = []; -var R = 0; +var re = exports.re = [] +var src = exports.src = [] +var R = 0 // The following Regular Expressions can be used for tokenizing, // validating, and parsing SemVer version strings. @@ -48433,71 +48438,67 @@ var R = 0; // ## Numeric Identifier // A single `0`, or a non-zero digit followed by zero or more digits. -var NUMERICIDENTIFIER = R++; -src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; -var NUMERICIDENTIFIERLOOSE = R++; -src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; - +var NUMERICIDENTIFIER = R++ +src[NUMERICIDENTIFIER] = '0|[1-9]\\d*' +var NUMERICIDENTIFIERLOOSE = R++ +src[NUMERICIDENTIFIERLOOSE] = '[0-9]+' // ## Non-numeric Identifier // Zero or more digits, followed by a letter or hyphen, and then zero or // more letters, digits, or hyphens. -var NONNUMERICIDENTIFIER = R++; -src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; - +var NONNUMERICIDENTIFIER = R++ +src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' // ## Main Version // Three dot-separated numeric identifiers. -var MAINVERSION = R++; +var MAINVERSION = R++ src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')'; + '(' + src[NUMERICIDENTIFIER] + ')' -var MAINVERSIONLOOSE = R++; +var MAINVERSIONLOOSE = R++ src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; + '(' + src[NUMERICIDENTIFIERLOOSE] + ')' // ## Pre-release Version Identifier // A numeric identifier, or a non-numeric identifier. -var PRERELEASEIDENTIFIER = R++; +var PRERELEASEIDENTIFIER = R++ src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + - '|' + src[NONNUMERICIDENTIFIER] + ')'; + '|' + src[NONNUMERICIDENTIFIER] + ')' -var PRERELEASEIDENTIFIERLOOSE = R++; +var PRERELEASEIDENTIFIERLOOSE = R++ src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + - '|' + src[NONNUMERICIDENTIFIER] + ')'; - + '|' + src[NONNUMERICIDENTIFIER] + ')' // ## Pre-release Version // Hyphen, followed by one or more dot-separated pre-release version // identifiers. -var PRERELEASE = R++; +var PRERELEASE = R++ src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + - '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))' -var PRERELEASELOOSE = R++; +var PRERELEASELOOSE = R++ src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + - '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))' // ## Build Metadata Identifier // Any combination of digits, letters, or hyphens. -var BUILDIDENTIFIER = R++; -src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; +var BUILDIDENTIFIER = R++ +src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+' // ## Build Metadata // Plus sign, followed by one or more period-separated build metadata // identifiers. -var BUILD = R++; +var BUILD = R++ src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + - '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; - + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))' // ## Full Version String // A main version, followed optionally by a pre-release version and @@ -48508,774 +48509,870 @@ src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + // capturing group, because it should not ever be used in version // comparison. -var FULL = R++; +var FULL = R++ var FULLPLAIN = 'v?' + src[MAINVERSION] + src[PRERELEASE] + '?' + - src[BUILD] + '?'; + src[BUILD] + '?' -src[FULL] = '^' + FULLPLAIN + '$'; +src[FULL] = '^' + FULLPLAIN + '$' // like full, but allows v1.2.3 and =1.2.3, which people do sometimes. // also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty // common in the npm registry. var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + src[PRERELEASELOOSE] + '?' + - src[BUILD] + '?'; + src[BUILD] + '?' -var LOOSE = R++; -src[LOOSE] = '^' + LOOSEPLAIN + '$'; +var LOOSE = R++ +src[LOOSE] = '^' + LOOSEPLAIN + '$' -var GTLT = R++; -src[GTLT] = '((?:<|>)?=?)'; +var GTLT = R++ +src[GTLT] = '((?:<|>)?=?)' // Something like "2.*" or "1.2.x". // Note that "x.x" is a valid xRange identifer, meaning "any version" // Only the first item is strictly required. -var XRANGEIDENTIFIERLOOSE = R++; -src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; -var XRANGEIDENTIFIER = R++; -src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; +var XRANGEIDENTIFIERLOOSE = R++ +src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' +var XRANGEIDENTIFIER = R++ +src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*' -var XRANGEPLAIN = R++; +var XRANGEPLAIN = R++ src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + '(?:' + src[PRERELEASE] + ')?' + src[BUILD] + '?' + - ')?)?'; + ')?)?' -var XRANGEPLAINLOOSE = R++; +var XRANGEPLAINLOOSE = R++ src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + '(?:' + src[PRERELEASELOOSE] + ')?' + src[BUILD] + '?' + - ')?)?'; + ')?)?' + +var XRANGE = R++ +src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$' +var XRANGELOOSE = R++ +src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$' -var XRANGE = R++; -src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; -var XRANGELOOSE = R++; -src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; +// Coercion. +// Extract anything that could conceivably be a part of a valid semver +var COERCE = R++ +src[COERCE] = '(?:^|[^\\d])' + + '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:$|[^\\d])' // Tilde ranges. // Meaning is "reasonably at or greater than" -var LONETILDE = R++; -src[LONETILDE] = '(?:~>?)'; +var LONETILDE = R++ +src[LONETILDE] = '(?:~>?)' -var TILDETRIM = R++; -src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; -re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); -var tildeTrimReplace = '$1~'; +var TILDETRIM = R++ +src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+' +re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g') +var tildeTrimReplace = '$1~' -var TILDE = R++; -src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; -var TILDELOOSE = R++; -src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; +var TILDE = R++ +src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$' +var TILDELOOSE = R++ +src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$' // Caret ranges. // Meaning is "at least and backwards compatible with" -var LONECARET = R++; -src[LONECARET] = '(?:\\^)'; +var LONECARET = R++ +src[LONECARET] = '(?:\\^)' -var CARETTRIM = R++; -src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; -re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); -var caretTrimReplace = '$1^'; +var CARETTRIM = R++ +src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+' +re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g') +var caretTrimReplace = '$1^' -var CARET = R++; -src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; -var CARETLOOSE = R++; -src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; +var CARET = R++ +src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$' +var CARETLOOSE = R++ +src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$' // A simple gt/lt/eq thing, or just "" to indicate "any version" -var COMPARATORLOOSE = R++; -src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; -var COMPARATOR = R++; -src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; - +var COMPARATORLOOSE = R++ +src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$' +var COMPARATOR = R++ +src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$' // An expression to strip any whitespace between the gtlt and the thing // it modifies, so that `> 1.2.3` ==> `>1.2.3` -var COMPARATORTRIM = R++; +var COMPARATORTRIM = R++ src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + - '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')' // this one has to use the /g flag -re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); -var comparatorTrimReplace = '$1$2$3'; - +re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g') +var comparatorTrimReplace = '$1$2$3' // Something like `1.2.3 - 1.2.4` // Note that these all use the loose form, because they'll be // checked against either the strict or loose comparator form // later. -var HYPHENRANGE = R++; +var HYPHENRANGE = R++ src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + '\\s+-\\s+' + '(' + src[XRANGEPLAIN] + ')' + - '\\s*$'; + '\\s*$' -var HYPHENRANGELOOSE = R++; +var HYPHENRANGELOOSE = R++ src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + '\\s+-\\s+' + '(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s*$'; + '\\s*$' // Star ranges basically just allow anything at all. -var STAR = R++; -src[STAR] = '(<|>)?=?\\s*\\*'; +var STAR = R++ +src[STAR] = '(<|>)?=?\\s*\\*' // Compile to actual regexp objects. // All are flag-free, unless they were created above with a flag. for (var i = 0; i < R; i++) { - debug(i, src[i]); - if (!re[i]) - re[i] = new RegExp(src[i]); + debug(i, src[i]) + if (!re[i]) { + re[i] = new RegExp(src[i]) + } } -exports.parse = parse; -function parse(version, loose) { - if (version instanceof SemVer) - return version; +exports.parse = parse +function parse (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (version instanceof SemVer) { + return version + } - if (typeof version !== 'string') - return null; + if (typeof version !== 'string') { + return null + } - if (version.length > MAX_LENGTH) - return null; + if (version.length > MAX_LENGTH) { + return null + } - var r = loose ? re[LOOSE] : re[FULL]; - if (!r.test(version)) - return null; + var r = options.loose ? re[LOOSE] : re[FULL] + if (!r.test(version)) { + return null + } try { - return new SemVer(version, loose); + return new SemVer(version, options) } catch (er) { - return null; + return null } } -exports.valid = valid; -function valid(version, loose) { - var v = parse(version, loose); - return v ? v.version : null; +exports.valid = valid +function valid (version, options) { + var v = parse(version, options) + return v ? v.version : null } - -exports.clean = clean; -function clean(version, loose) { - var s = parse(version.trim().replace(/^[=v]+/, ''), loose); - return s ? s.version : null; +exports.clean = clean +function clean (version, options) { + var s = parse(version.trim().replace(/^[=v]+/, ''), options) + return s ? s.version : null } -exports.SemVer = SemVer; +exports.SemVer = SemVer -function SemVer(version, loose) { +function SemVer (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } if (version instanceof SemVer) { - if (version.loose === loose) - return version; - else - version = version.version; + if (version.loose === options.loose) { + return version + } else { + version = version.version + } } else if (typeof version !== 'string') { - throw new TypeError('Invalid Version: ' + version); + throw new TypeError('Invalid Version: ' + version) } - if (version.length > MAX_LENGTH) + if (version.length > MAX_LENGTH) { throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') + } + + if (!(this instanceof SemVer)) { + return new SemVer(version, options) + } - if (!(this instanceof SemVer)) - return new SemVer(version, loose); + debug('SemVer', version, options) + this.options = options + this.loose = !!options.loose - debug('SemVer', version, loose); - this.loose = loose; - var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); + var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL]) - if (!m) - throw new TypeError('Invalid Version: ' + version); + if (!m) { + throw new TypeError('Invalid Version: ' + version) + } - this.raw = version; + this.raw = version // these are actually numbers - this.major = +m[1]; - this.minor = +m[2]; - this.patch = +m[3]; + this.major = +m[1] + this.minor = +m[2] + this.patch = +m[3] - if (this.major > MAX_SAFE_INTEGER || this.major < 0) + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { throw new TypeError('Invalid major version') + } - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { throw new TypeError('Invalid minor version') + } - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { throw new TypeError('Invalid patch version') + } // numberify any prerelease numeric ids - if (!m[4]) - this.prerelease = []; - else - this.prerelease = m[4].split('.').map(function(id) { + if (!m[4]) { + this.prerelease = [] + } else { + this.prerelease = m[4].split('.').map(function (id) { if (/^[0-9]+$/.test(id)) { - var num = +id; - if (num >= 0 && num < MAX_SAFE_INTEGER) - return num; + var num = +id + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num + } } - return id; - }); + return id + }) + } - this.build = m[5] ? m[5].split('.') : []; - this.format(); + this.build = m[5] ? m[5].split('.') : [] + this.format() } -SemVer.prototype.format = function() { - this.version = this.major + '.' + this.minor + '.' + this.patch; - if (this.prerelease.length) - this.version += '-' + this.prerelease.join('.'); - return this.version; -}; +SemVer.prototype.format = function () { + this.version = this.major + '.' + this.minor + '.' + this.patch + if (this.prerelease.length) { + this.version += '-' + this.prerelease.join('.') + } + return this.version +} -SemVer.prototype.toString = function() { - return this.version; -}; +SemVer.prototype.toString = function () { + return this.version +} -SemVer.prototype.compare = function(other) { - debug('SemVer.compare', this.version, this.loose, other); - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); +SemVer.prototype.compare = function (other) { + debug('SemVer.compare', this.version, this.options, other) + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } - return this.compareMain(other) || this.comparePre(other); -}; + return this.compareMain(other) || this.comparePre(other) +} -SemVer.prototype.compareMain = function(other) { - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); +SemVer.prototype.compareMain = function (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch); -}; + compareIdentifiers(this.patch, other.patch) +} -SemVer.prototype.comparePre = function(other) { - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); +SemVer.prototype.comparePre = function (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) - return -1; - else if (!this.prerelease.length && other.prerelease.length) - return 1; - else if (!this.prerelease.length && !other.prerelease.length) - return 0; + if (this.prerelease.length && !other.prerelease.length) { + return -1 + } else if (!this.prerelease.length && other.prerelease.length) { + return 1 + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0 + } - var i = 0; + var i = 0 do { - var a = this.prerelease[i]; - var b = other.prerelease[i]; - debug('prerelease compare', i, a, b); - if (a === undefined && b === undefined) - return 0; - else if (b === undefined) - return 1; - else if (a === undefined) - return -1; - else if (a === b) - continue; - else - return compareIdentifiers(a, b); - } while (++i); -}; + var a = this.prerelease[i] + var b = other.prerelease[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) +} // preminor will bump the version up to the next minor release, and immediately // down to pre-release. premajor and prepatch work the same way. -SemVer.prototype.inc = function(release, identifier) { +SemVer.prototype.inc = function (release, identifier) { switch (release) { case 'premajor': - this.prerelease.length = 0; - this.patch = 0; - this.minor = 0; - this.major++; - this.inc('pre', identifier); - break; + this.prerelease.length = 0 + this.patch = 0 + this.minor = 0 + this.major++ + this.inc('pre', identifier) + break case 'preminor': - this.prerelease.length = 0; - this.patch = 0; - this.minor++; - this.inc('pre', identifier); - break; + this.prerelease.length = 0 + this.patch = 0 + this.minor++ + this.inc('pre', identifier) + break case 'prepatch': // If this is already a prerelease, it will bump to the next version // drop any prereleases that might already exist, since they are not // relevant at this point. - this.prerelease.length = 0; - this.inc('patch', identifier); - this.inc('pre', identifier); - break; + this.prerelease.length = 0 + this.inc('patch', identifier) + this.inc('pre', identifier) + break // If the input is a non-prerelease version, this acts the same as // prepatch. case 'prerelease': - if (this.prerelease.length === 0) - this.inc('patch', identifier); - this.inc('pre', identifier); - break; + if (this.prerelease.length === 0) { + this.inc('patch', identifier) + } + this.inc('pre', identifier) + break case 'major': // If this is a pre-major version, bump up to the same major version. // Otherwise increment major. // 1.0.0-5 bumps to 1.0.0 // 1.1.0 bumps to 2.0.0 - if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) - this.major++; - this.minor = 0; - this.patch = 0; - this.prerelease = []; - break; + if (this.minor !== 0 || + this.patch !== 0 || + this.prerelease.length === 0) { + this.major++ + } + this.minor = 0 + this.patch = 0 + this.prerelease = [] + break case 'minor': // If this is a pre-minor version, bump up to the same minor version. // Otherwise increment minor. // 1.2.0-5 bumps to 1.2.0 // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) - this.minor++; - this.patch = 0; - this.prerelease = []; - break; + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++ + } + this.patch = 0 + this.prerelease = [] + break case 'patch': // If this is not a pre-release version, it will increment the patch. // If it is a pre-release it will bump up to the same patch version. // 1.2.0-5 patches to 1.2.0 // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) - this.patch++; - this.prerelease = []; - break; + if (this.prerelease.length === 0) { + this.patch++ + } + this.prerelease = [] + break // This probably shouldn't be used publicly. // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. case 'pre': - if (this.prerelease.length === 0) - this.prerelease = [0]; - else { - var i = this.prerelease.length; + if (this.prerelease.length === 0) { + this.prerelease = [0] + } else { + var i = this.prerelease.length while (--i >= 0) { if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++; - i = -2; + this.prerelease[i]++ + i = -2 } } - if (i === -1) // didn't increment anything - this.prerelease.push(0); + if (i === -1) { + // didn't increment anything + this.prerelease.push(0) + } } if (identifier) { // 1.2.0-beta.1 bumps to 1.2.0-beta.2, // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) - this.prerelease = [identifier, 0]; - } else - this.prerelease = [identifier, 0]; + if (isNaN(this.prerelease[1])) { + this.prerelease = [identifier, 0] + } + } else { + this.prerelease = [identifier, 0] + } } - break; + break default: - throw new Error('invalid increment argument: ' + release); + throw new Error('invalid increment argument: ' + release) } - this.format(); - this.raw = this.version; - return this; -}; + this.format() + this.raw = this.version + return this +} -exports.inc = inc; -function inc(version, release, loose, identifier) { - if (typeof(loose) === 'string') { - identifier = loose; - loose = undefined; +exports.inc = inc +function inc (version, release, loose, identifier) { + if (typeof (loose) === 'string') { + identifier = loose + loose = undefined } try { - return new SemVer(version, loose).inc(release, identifier).version; + return new SemVer(version, loose).inc(release, identifier).version } catch (er) { - return null; + return null } } -exports.diff = diff; -function diff(version1, version2) { +exports.diff = diff +function diff (version1, version2) { if (eq(version1, version2)) { - return null; + return null } else { - var v1 = parse(version1); - var v2 = parse(version2); + var v1 = parse(version1) + var v2 = parse(version2) + var prefix = '' if (v1.prerelease.length || v2.prerelease.length) { - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return 'pre'+key; - } - } - } - return 'prerelease'; + prefix = 'pre' + var defaultResult = 'prerelease' } for (var key in v1) { if (key === 'major' || key === 'minor' || key === 'patch') { if (v1[key] !== v2[key]) { - return key; + return prefix + key } } } + return defaultResult // may be undefined } } -exports.compareIdentifiers = compareIdentifiers; +exports.compareIdentifiers = compareIdentifiers -var numeric = /^[0-9]+$/; -function compareIdentifiers(a, b) { - var anum = numeric.test(a); - var bnum = numeric.test(b); +var numeric = /^[0-9]+$/ +function compareIdentifiers (a, b) { + var anum = numeric.test(a) + var bnum = numeric.test(b) if (anum && bnum) { - a = +a; - b = +b; + a = +a + b = +b } - return (anum && !bnum) ? -1 : - (bnum && !anum) ? 1 : - a < b ? -1 : - a > b ? 1 : - 0; + return a === b ? 0 + : (anum && !bnum) ? -1 + : (bnum && !anum) ? 1 + : a < b ? -1 + : 1 } -exports.rcompareIdentifiers = rcompareIdentifiers; -function rcompareIdentifiers(a, b) { - return compareIdentifiers(b, a); +exports.rcompareIdentifiers = rcompareIdentifiers +function rcompareIdentifiers (a, b) { + return compareIdentifiers(b, a) } -exports.major = major; -function major(a, loose) { - return new SemVer(a, loose).major; +exports.major = major +function major (a, loose) { + return new SemVer(a, loose).major } -exports.minor = minor; -function minor(a, loose) { - return new SemVer(a, loose).minor; +exports.minor = minor +function minor (a, loose) { + return new SemVer(a, loose).minor } -exports.patch = patch; -function patch(a, loose) { - return new SemVer(a, loose).patch; +exports.patch = patch +function patch (a, loose) { + return new SemVer(a, loose).patch } -exports.compare = compare; -function compare(a, b, loose) { - return new SemVer(a, loose).compare(new SemVer(b, loose)); +exports.compare = compare +function compare (a, b, loose) { + return new SemVer(a, loose).compare(new SemVer(b, loose)) } -exports.compareLoose = compareLoose; -function compareLoose(a, b) { - return compare(a, b, true); +exports.compareLoose = compareLoose +function compareLoose (a, b) { + return compare(a, b, true) } -exports.rcompare = rcompare; -function rcompare(a, b, loose) { - return compare(b, a, loose); +exports.rcompare = rcompare +function rcompare (a, b, loose) { + return compare(b, a, loose) } -exports.sort = sort; -function sort(list, loose) { - return list.sort(function(a, b) { - return exports.compare(a, b, loose); - }); +exports.sort = sort +function sort (list, loose) { + return list.sort(function (a, b) { + return exports.compare(a, b, loose) + }) } -exports.rsort = rsort; -function rsort(list, loose) { - return list.sort(function(a, b) { - return exports.rcompare(a, b, loose); - }); +exports.rsort = rsort +function rsort (list, loose) { + return list.sort(function (a, b) { + return exports.rcompare(a, b, loose) + }) } -exports.gt = gt; -function gt(a, b, loose) { - return compare(a, b, loose) > 0; +exports.gt = gt +function gt (a, b, loose) { + return compare(a, b, loose) > 0 } -exports.lt = lt; -function lt(a, b, loose) { - return compare(a, b, loose) < 0; +exports.lt = lt +function lt (a, b, loose) { + return compare(a, b, loose) < 0 } -exports.eq = eq; -function eq(a, b, loose) { - return compare(a, b, loose) === 0; +exports.eq = eq +function eq (a, b, loose) { + return compare(a, b, loose) === 0 } -exports.neq = neq; -function neq(a, b, loose) { - return compare(a, b, loose) !== 0; +exports.neq = neq +function neq (a, b, loose) { + return compare(a, b, loose) !== 0 } -exports.gte = gte; -function gte(a, b, loose) { - return compare(a, b, loose) >= 0; +exports.gte = gte +function gte (a, b, loose) { + return compare(a, b, loose) >= 0 } -exports.lte = lte; -function lte(a, b, loose) { - return compare(a, b, loose) <= 0; +exports.lte = lte +function lte (a, b, loose) { + return compare(a, b, loose) <= 0 } -exports.cmp = cmp; -function cmp(a, op, b, loose) { - var ret; +exports.cmp = cmp +function cmp (a, op, b, loose) { switch (op) { case '===': - if (typeof a === 'object') a = a.version; - if (typeof b === 'object') b = b.version; - ret = a === b; - break; - case '!==': - if (typeof a === 'object') a = a.version; - if (typeof b === 'object') b = b.version; - ret = a !== b; - break; - case '': case '=': case '==': ret = eq(a, b, loose); break; - case '!=': ret = neq(a, b, loose); break; - case '>': ret = gt(a, b, loose); break; - case '>=': ret = gte(a, b, loose); break; - case '<': ret = lt(a, b, loose); break; - case '<=': ret = lte(a, b, loose); break; - default: throw new TypeError('Invalid operator: ' + op); - } - return ret; -} - -exports.Comparator = Comparator; -function Comparator(comp, loose) { - if (comp instanceof Comparator) { - if (comp.loose === loose) - return comp; - else - comp = comp.value; - } - - if (!(this instanceof Comparator)) - return new Comparator(comp, loose); + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a === b - debug('comparator', comp, loose); - this.loose = loose; - this.parse(comp); + case '!==': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a !== b - if (this.semver === ANY) - this.value = ''; - else - this.value = this.operator + this.semver.version; + case '': + case '=': + case '==': + return eq(a, b, loose) - debug('comp', this); -} + case '!=': + return neq(a, b, loose) -var ANY = {}; -Comparator.prototype.parse = function(comp) { - var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; - var m = comp.match(r); + case '>': + return gt(a, b, loose) - if (!m) - throw new TypeError('Invalid comparator: ' + comp); + case '>=': + return gte(a, b, loose) - this.operator = m[1]; - if (this.operator === '=') - this.operator = ''; + case '<': + return lt(a, b, loose) - // if it literally is just '>' or '' then allow anything. - if (!m[2]) - this.semver = ANY; - else - this.semver = new SemVer(m[2], this.loose); -}; + case '<=': + return lte(a, b, loose) -Comparator.prototype.toString = function() { - return this.value; -}; + default: + throw new TypeError('Invalid operator: ' + op) + } +} -Comparator.prototype.test = function(version) { - debug('Comparator.test', version, this.loose); +exports.Comparator = Comparator +function Comparator (comp, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } - if (this.semver === ANY) - return true; + if (comp instanceof Comparator) { + if (comp.loose === !!options.loose) { + return comp + } else { + comp = comp.value + } + } - if (typeof version === 'string') - version = new SemVer(version, this.loose); + if (!(this instanceof Comparator)) { + return new Comparator(comp, options) + } - return cmp(version, this.operator, this.semver, this.loose); -}; + debug('comparator', comp, options) + this.options = options + this.loose = !!options.loose + this.parse(comp) -Comparator.prototype.intersects = function(comp, loose) { - if (!(comp instanceof Comparator)) { - throw new TypeError('a Comparator is required'); + if (this.semver === ANY) { + this.value = '' + } else { + this.value = this.operator + this.semver.version } - var rangeTmp; - + debug('comp', this) +} + +var ANY = {} +Comparator.prototype.parse = function (comp) { + var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR] + var m = comp.match(r) + + if (!m) { + throw new TypeError('Invalid comparator: ' + comp) + } + + this.operator = m[1] + if (this.operator === '=') { + this.operator = '' + } + + // if it literally is just '>' or '' then allow anything. + if (!m[2]) { + this.semver = ANY + } else { + this.semver = new SemVer(m[2], this.options.loose) + } +} + +Comparator.prototype.toString = function () { + return this.value +} + +Comparator.prototype.test = function (version) { + debug('Comparator.test', version, this.options.loose) + + if (this.semver === ANY) { + return true + } + + if (typeof version === 'string') { + version = new SemVer(version, this.options) + } + + return cmp(version, this.operator, this.semver, this.options) +} + +Comparator.prototype.intersects = function (comp, options) { + if (!(comp instanceof Comparator)) { + throw new TypeError('a Comparator is required') + } + + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + var rangeTmp + if (this.operator === '') { - rangeTmp = new Range(comp.value, loose); - return satisfies(this.value, rangeTmp, loose); + rangeTmp = new Range(comp.value, options) + return satisfies(this.value, rangeTmp, options) } else if (comp.operator === '') { - rangeTmp = new Range(this.value, loose); - return satisfies(comp.semver, rangeTmp, loose); + rangeTmp = new Range(this.value, options) + return satisfies(comp.semver, rangeTmp, options) } var sameDirectionIncreasing = (this.operator === '>=' || this.operator === '>') && - (comp.operator === '>=' || comp.operator === '>'); + (comp.operator === '>=' || comp.operator === '>') var sameDirectionDecreasing = (this.operator === '<=' || this.operator === '<') && - (comp.operator === '<=' || comp.operator === '<'); - var sameSemVer = this.semver.version === comp.semver.version; + (comp.operator === '<=' || comp.operator === '<') + var sameSemVer = this.semver.version === comp.semver.version var differentDirectionsInclusive = (this.operator === '>=' || this.operator === '<=') && - (comp.operator === '>=' || comp.operator === '<='); + (comp.operator === '>=' || comp.operator === '<=') var oppositeDirectionsLessThan = - cmp(this.semver, '<', comp.semver, loose) && + cmp(this.semver, '<', comp.semver, options) && ((this.operator === '>=' || this.operator === '>') && - (comp.operator === '<=' || comp.operator === '<')); + (comp.operator === '<=' || comp.operator === '<')) var oppositeDirectionsGreaterThan = - cmp(this.semver, '>', comp.semver, loose) && + cmp(this.semver, '>', comp.semver, options) && ((this.operator === '<=' || this.operator === '<') && - (comp.operator === '>=' || comp.operator === '>')); + (comp.operator === '>=' || comp.operator === '>')) return sameDirectionIncreasing || sameDirectionDecreasing || (sameSemVer && differentDirectionsInclusive) || - oppositeDirectionsLessThan || oppositeDirectionsGreaterThan; -}; + oppositeDirectionsLessThan || oppositeDirectionsGreaterThan +} +exports.Range = Range +function Range (range, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } -exports.Range = Range; -function Range(range, loose) { if (range instanceof Range) { - if (range.loose === loose) { - return range; + if (range.loose === !!options.loose && + range.includePrerelease === !!options.includePrerelease) { + return range } else { - return new Range(range.raw, loose); + return new Range(range.raw, options) } } if (range instanceof Comparator) { - return new Range(range.value, loose); + return new Range(range.value, options) } - if (!(this instanceof Range)) - return new Range(range, loose); + if (!(this instanceof Range)) { + return new Range(range, options) + } - this.loose = loose; + this.options = options + this.loose = !!options.loose + this.includePrerelease = !!options.includePrerelease // First, split based on boolean or || - this.raw = range; - this.set = range.split(/\s*\|\|\s*/).map(function(range) { - return this.parseRange(range.trim()); - }, this).filter(function(c) { + this.raw = range + this.set = range.split(/\s*\|\|\s*/).map(function (range) { + return this.parseRange(range.trim()) + }, this).filter(function (c) { // throw out any that are not relevant for whatever reason - return c.length; - }); + return c.length + }) if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + range); + throw new TypeError('Invalid SemVer Range: ' + range) } - this.format(); + this.format() } -Range.prototype.format = function() { - this.range = this.set.map(function(comps) { - return comps.join(' ').trim(); - }).join('||').trim(); - return this.range; -}; +Range.prototype.format = function () { + this.range = this.set.map(function (comps) { + return comps.join(' ').trim() + }).join('||').trim() + return this.range +} -Range.prototype.toString = function() { - return this.range; -}; +Range.prototype.toString = function () { + return this.range +} -Range.prototype.parseRange = function(range) { - var loose = this.loose; - range = range.trim(); - debug('range', range, loose); +Range.prototype.parseRange = function (range) { + var loose = this.options.loose + range = range.trim() // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; - range = range.replace(hr, hyphenReplace); - debug('hyphen replace', range); + var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE] + range = range.replace(hr, hyphenReplace) + debug('hyphen replace', range) // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); - debug('comparator trim', range, re[COMPARATORTRIM]); + range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace) + debug('comparator trim', range, re[COMPARATORTRIM]) // `~ 1.2.3` => `~1.2.3` - range = range.replace(re[TILDETRIM], tildeTrimReplace); + range = range.replace(re[TILDETRIM], tildeTrimReplace) // `^ 1.2.3` => `^1.2.3` - range = range.replace(re[CARETTRIM], caretTrimReplace); + range = range.replace(re[CARETTRIM], caretTrimReplace) // normalize spaces - range = range.split(/\s+/).join(' '); + range = range.split(/\s+/).join(' ') // At this point, the range is completely trimmed and // ready to be split into comparators. - var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; - var set = range.split(' ').map(function(comp) { - return parseComparator(comp, loose); - }).join(' ').split(/\s+/); - if (this.loose) { + var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR] + var set = range.split(' ').map(function (comp) { + return parseComparator(comp, this.options) + }, this).join(' ').split(/\s+/) + if (this.options.loose) { // in loose mode, throw out any that are not valid comparators - set = set.filter(function(comp) { - return !!comp.match(compRe); - }); + set = set.filter(function (comp) { + return !!comp.match(compRe) + }) } - set = set.map(function(comp) { - return new Comparator(comp, loose); - }); + set = set.map(function (comp) { + return new Comparator(comp, this.options) + }, this) - return set; -}; + return set +} -Range.prototype.intersects = function(range, loose) { +Range.prototype.intersects = function (range, options) { if (!(range instanceof Range)) { - throw new TypeError('a Range is required'); + throw new TypeError('a Range is required') } - return this.set.some(function(thisComparators) { - return thisComparators.every(function(thisComparator) { - return range.set.some(function(rangeComparators) { - return rangeComparators.every(function(rangeComparator) { - return thisComparator.intersects(rangeComparator, loose); - }); - }); - }); - }); -}; + return this.set.some(function (thisComparators) { + return thisComparators.every(function (thisComparator) { + return range.set.some(function (rangeComparators) { + return rangeComparators.every(function (rangeComparator) { + return thisComparator.intersects(rangeComparator, options) + }) + }) + }) + }) +} // Mostly just for testing and legacy API reasons -exports.toComparators = toComparators; -function toComparators(range, loose) { - return new Range(range, loose).set.map(function(comp) { - return comp.map(function(c) { - return c.value; - }).join(' ').trim().split(' '); - }); +exports.toComparators = toComparators +function toComparators (range, options) { + return new Range(range, options).set.map(function (comp) { + return comp.map(function (c) { + return c.value + }).join(' ').trim().split(' ') + }) } // comprised of xranges, tildes, stars, and gtlt's at this point. // already replaced the hyphen ranges // turn into a set of JUST comparators. -function parseComparator(comp, loose) { - debug('comp', comp); - comp = replaceCarets(comp, loose); - debug('caret', comp); - comp = replaceTildes(comp, loose); - debug('tildes', comp); - comp = replaceXRanges(comp, loose); - debug('xrange', comp); - comp = replaceStars(comp, loose); - debug('stars', comp); - return comp; +function parseComparator (comp, options) { + debug('comp', comp, options) + comp = replaceCarets(comp, options) + debug('caret', comp) + comp = replaceTildes(comp, options) + debug('tildes', comp) + comp = replaceXRanges(comp, options) + debug('xrange', comp) + comp = replaceStars(comp, options) + debug('stars', comp) + return comp } -function isX(id) { - return !id || id.toLowerCase() === 'x' || id === '*'; +function isX (id) { + return !id || id.toLowerCase() === 'x' || id === '*' } // ~, ~> --> * (any, kinda silly) @@ -49284,39 +49381,38 @@ function isX(id) { // ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 // ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 // ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 -function replaceTildes(comp, loose) { - return comp.trim().split(/\s+/).map(function(comp) { - return replaceTilde(comp, loose); - }).join(' '); -} - -function replaceTilde(comp, loose) { - var r = loose ? re[TILDELOOSE] : re[TILDE]; - return comp.replace(r, function(_, M, m, p, pr) { - debug('tilde', comp, _, M, m, p, pr); - var ret; - - if (isX(M)) - ret = ''; - else if (isX(m)) - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - else if (isX(p)) +function replaceTildes (comp, options) { + return comp.trim().split(/\s+/).map(function (comp) { + return replaceTilde(comp, options) + }).join(' ') +} + +function replaceTilde (comp, options) { + var r = options.loose ? re[TILDELOOSE] : re[TILDE] + return comp.replace(r, function (_, M, m, p, pr) { + debug('tilde', comp, _, M, m, p, pr) + var ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (isX(p)) { // ~1.2 == >=1.2.0 <1.3.0 - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - else if (pr) { - debug('replaceTilde pr', pr); - if (pr.charAt(0) !== '-') - pr = '-' + pr; - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + (+m + 1) + '.0'; - } else + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } else if (pr) { + debug('replaceTilde pr', pr) + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + (+m + 1) + '.0' + } else { // ~1.2.3 == >=1.2.3 <1.3.0 ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0'; + ' <' + M + '.' + (+m + 1) + '.0' + } - debug('tilde return', ret); - return ret; - }); + debug('tilde return', ret) + return ret + }) } // ^ --> * (any, kinda silly) @@ -49325,138 +49421,144 @@ function replaceTilde(comp, loose) { // ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 // ^1.2.3 --> >=1.2.3 <2.0.0 // ^1.2.0 --> >=1.2.0 <2.0.0 -function replaceCarets(comp, loose) { - return comp.trim().split(/\s+/).map(function(comp) { - return replaceCaret(comp, loose); - }).join(' '); -} - -function replaceCaret(comp, loose) { - debug('caret', comp, loose); - var r = loose ? re[CARETLOOSE] : re[CARET]; - return comp.replace(r, function(_, M, m, p, pr) { - debug('caret', comp, _, M, m, p, pr); - var ret; - - if (isX(M)) - ret = ''; - else if (isX(m)) - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - else if (isX(p)) { - if (M === '0') - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - else - ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'; +function replaceCarets (comp, options) { + return comp.trim().split(/\s+/).map(function (comp) { + return replaceCaret(comp, options) + }).join(' ') +} + +function replaceCaret (comp, options) { + debug('caret', comp, options) + var r = options.loose ? re[CARETLOOSE] : re[CARET] + return comp.replace(r, function (_, M, m, p, pr) { + debug('caret', comp, _, M, m, p, pr) + var ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (isX(p)) { + if (M === '0') { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } else { + ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' + } } else if (pr) { - debug('replaceCaret pr', pr); - if (pr.charAt(0) !== '-') - pr = '-' + pr; + debug('replaceCaret pr', pr) if (M === '0') { - if (m === '0') - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + m + '.' + (+p + 1); - else - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + (+M + 1) + '.0.0'; + if (m === '0') { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + m + '.' + (+p + 1) + } else { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + (+m + 1) + '.0' + } + } else { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + (+M + 1) + '.0.0' + } } else { - debug('no pr'); + debug('no pr') if (M === '0') { - if (m === '0') + if (m === '0') { ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + m + '.' + (+p + 1); - else + ' <' + M + '.' + m + '.' + (+p + 1) + } else { ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0'; - } else + ' <' + M + '.' + (+m + 1) + '.0' + } + } else { ret = '>=' + M + '.' + m + '.' + p + - ' <' + (+M + 1) + '.0.0'; + ' <' + (+M + 1) + '.0.0' + } } - debug('caret return', ret); - return ret; - }); + debug('caret return', ret) + return ret + }) } -function replaceXRanges(comp, loose) { - debug('replaceXRanges', comp, loose); - return comp.split(/\s+/).map(function(comp) { - return replaceXRange(comp, loose); - }).join(' '); +function replaceXRanges (comp, options) { + debug('replaceXRanges', comp, options) + return comp.split(/\s+/).map(function (comp) { + return replaceXRange(comp, options) + }).join(' ') } -function replaceXRange(comp, loose) { - comp = comp.trim(); - var r = loose ? re[XRANGELOOSE] : re[XRANGE]; - return comp.replace(r, function(ret, gtlt, M, m, p, pr) { - debug('xRange', comp, ret, gtlt, M, m, p, pr); - var xM = isX(M); - var xm = xM || isX(m); - var xp = xm || isX(p); - var anyX = xp; +function replaceXRange (comp, options) { + comp = comp.trim() + var r = options.loose ? re[XRANGELOOSE] : re[XRANGE] + return comp.replace(r, function (ret, gtlt, M, m, p, pr) { + debug('xRange', comp, ret, gtlt, M, m, p, pr) + var xM = isX(M) + var xm = xM || isX(m) + var xp = xm || isX(p) + var anyX = xp - if (gtlt === '=' && anyX) - gtlt = ''; + if (gtlt === '=' && anyX) { + gtlt = '' + } if (xM) { if (gtlt === '>' || gtlt === '<') { // nothing is allowed - ret = '<0.0.0'; + ret = '<0.0.0' } else { // nothing is forbidden - ret = '*'; + ret = '*' } } else if (gtlt && anyX) { + // we know patch is an x, because we have any x at all. // replace X with 0 - if (xm) - m = 0; - if (xp) - p = 0; + if (xm) { + m = 0 + } + p = 0 if (gtlt === '>') { // >1 => >=2.0.0 // >1.2 => >=1.3.0 // >1.2.3 => >= 1.2.4 - gtlt = '>='; + gtlt = '>=' if (xm) { - M = +M + 1; - m = 0; - p = 0; - } else if (xp) { - m = +m + 1; - p = 0; + M = +M + 1 + m = 0 + p = 0 + } else { + m = +m + 1 + p = 0 } } else if (gtlt === '<=') { // <=0.7.x is actually <0.8.0, since any 0.7.x should // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<'; - if (xm) - M = +M + 1; - else - m = +m + 1; + gtlt = '<' + if (xm) { + M = +M + 1 + } else { + m = +m + 1 + } } - ret = gtlt + M + '.' + m + '.' + p; + ret = gtlt + M + '.' + m + '.' + p } else if (xm) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' } else if (xp) { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' } - debug('xRange return', ret); + debug('xRange return', ret) - return ret; - }); + return ret + }) } // Because * is AND-ed with everything else in the comparator, // and '' means "any version", just remove the *s entirely. -function replaceStars(comp, loose) { - debug('replaceStars', comp, loose); +function replaceStars (comp, options) { + debug('replaceStars', comp, options) // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(re[STAR], ''); + return comp.trim().replace(re[STAR], '') } // This function is passed to string.replace(re[HYPHENRANGE]) @@ -49464,238 +49566,323 @@ function replaceStars(comp, loose) { // 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 // 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do // 1.2 - 3.4 => >=1.2.0 <3.5.0 -function hyphenReplace($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr, tb) { - - if (isX(fM)) - from = ''; - else if (isX(fm)) - from = '>=' + fM + '.0.0'; - else if (isX(fp)) - from = '>=' + fM + '.' + fm + '.0'; - else - from = '>=' + from; - - if (isX(tM)) - to = ''; - else if (isX(tm)) - to = '<' + (+tM + 1) + '.0.0'; - else if (isX(tp)) - to = '<' + tM + '.' + (+tm + 1) + '.0'; - else if (tpr) - to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; - else - to = '<=' + to; +function hyphenReplace ($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) { + if (isX(fM)) { + from = '' + } else if (isX(fm)) { + from = '>=' + fM + '.0.0' + } else if (isX(fp)) { + from = '>=' + fM + '.' + fm + '.0' + } else { + from = '>=' + from + } - return (from + ' ' + to).trim(); -} + if (isX(tM)) { + to = '' + } else if (isX(tm)) { + to = '<' + (+tM + 1) + '.0.0' + } else if (isX(tp)) { + to = '<' + tM + '.' + (+tm + 1) + '.0' + } else if (tpr) { + to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr + } else { + to = '<=' + to + } + return (from + ' ' + to).trim() +} // if ANY of the sets match ALL of its comparators, then pass -Range.prototype.test = function(version) { - if (!version) - return false; +Range.prototype.test = function (version) { + if (!version) { + return false + } - if (typeof version === 'string') - version = new SemVer(version, this.loose); + if (typeof version === 'string') { + version = new SemVer(version, this.options) + } for (var i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version)) - return true; + if (testSet(this.set[i], version, this.options)) { + return true + } } - return false; -}; + return false +} -function testSet(set, version) { +function testSet (set, version, options) { for (var i = 0; i < set.length; i++) { - if (!set[i].test(version)) - return false; + if (!set[i].test(version)) { + return false + } } - if (version.prerelease.length) { + if (version.prerelease.length && !options.includePrerelease) { // Find the set of versions that are allowed to have prereleases // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 // That should allow `1.2.3-pr.2` to pass. // However, `1.2.4-alpha.notready` should NOT be allowed, // even though it's within the range set by the comparators. - for (var i = 0; i < set.length; i++) { - debug(set[i].semver); - if (set[i].semver === ANY) - continue; + for (i = 0; i < set.length; i++) { + debug(set[i].semver) + if (set[i].semver === ANY) { + continue + } if (set[i].semver.prerelease.length > 0) { - var allowed = set[i].semver; + var allowed = set[i].semver if (allowed.major === version.major && allowed.minor === version.minor && - allowed.patch === version.patch) - return true; + allowed.patch === version.patch) { + return true + } } } // Version has a -pre, but it's not one of the ones we like. - return false; + return false } - return true; + return true } -exports.satisfies = satisfies; -function satisfies(version, range, loose) { +exports.satisfies = satisfies +function satisfies (version, range, options) { try { - range = new Range(range, loose); + range = new Range(range, options) } catch (er) { - return false; + return false } - return range.test(version); + return range.test(version) } -exports.maxSatisfying = maxSatisfying; -function maxSatisfying(versions, range, loose) { - var max = null; - var maxSV = null; +exports.maxSatisfying = maxSatisfying +function maxSatisfying (versions, range, options) { + var max = null + var maxSV = null try { - var rangeObj = new Range(range, loose); + var rangeObj = new Range(range, options) } catch (er) { - return null; + return null } versions.forEach(function (v) { - if (rangeObj.test(v)) { // satisfies(v, range, loose) - if (!max || maxSV.compare(v) === -1) { // compare(max, v, true) - max = v; - maxSV = new SemVer(max, loose); + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!max || maxSV.compare(v) === -1) { + // compare(max, v, true) + max = v + maxSV = new SemVer(max, options) } } }) - return max; + return max } -exports.minSatisfying = minSatisfying; -function minSatisfying(versions, range, loose) { - var min = null; - var minSV = null; +exports.minSatisfying = minSatisfying +function minSatisfying (versions, range, options) { + var min = null + var minSV = null try { - var rangeObj = new Range(range, loose); + var rangeObj = new Range(range, options) } catch (er) { - return null; + return null } versions.forEach(function (v) { - if (rangeObj.test(v)) { // satisfies(v, range, loose) - if (!min || minSV.compare(v) === 1) { // compare(min, v, true) - min = v; - minSV = new SemVer(min, loose); + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!min || minSV.compare(v) === 1) { + // compare(min, v, true) + min = v + minSV = new SemVer(min, options) } } }) - return min; + return min +} + +exports.minVersion = minVersion +function minVersion (range, loose) { + range = new Range(range, loose) + + var minver = new SemVer('0.0.0') + if (range.test(minver)) { + return minver + } + + minver = new SemVer('0.0.0-0') + if (range.test(minver)) { + return minver + } + + minver = null + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i] + + comparators.forEach(function (comparator) { + // Clone to avoid manipulating the comparator's semver object. + var compver = new SemVer(comparator.semver.version) + switch (comparator.operator) { + case '>': + if (compver.prerelease.length === 0) { + compver.patch++ + } else { + compver.prerelease.push(0) + } + compver.raw = compver.format() + /* fallthrough */ + case '': + case '>=': + if (!minver || gt(minver, compver)) { + minver = compver + } + break + case '<': + case '<=': + /* Ignore maximum versions */ + break + /* istanbul ignore next */ + default: + throw new Error('Unexpected operation: ' + comparator.operator) + } + }) + } + + if (minver && range.test(minver)) { + return minver + } + + return null } -exports.validRange = validRange; -function validRange(range, loose) { +exports.validRange = validRange +function validRange (range, options) { try { // Return '*' instead of '' so that truthiness works. // This will throw if it's invalid anyway - return new Range(range, loose).range || '*'; + return new Range(range, options).range || '*' } catch (er) { - return null; + return null } } // Determine if version is less than all the versions possible in the range -exports.ltr = ltr; -function ltr(version, range, loose) { - return outside(version, range, '<', loose); +exports.ltr = ltr +function ltr (version, range, options) { + return outside(version, range, '<', options) } // Determine if version is greater than all the versions possible in the range. -exports.gtr = gtr; -function gtr(version, range, loose) { - return outside(version, range, '>', loose); +exports.gtr = gtr +function gtr (version, range, options) { + return outside(version, range, '>', options) } -exports.outside = outside; -function outside(version, range, hilo, loose) { - version = new SemVer(version, loose); - range = new Range(range, loose); +exports.outside = outside +function outside (version, range, hilo, options) { + version = new SemVer(version, options) + range = new Range(range, options) - var gtfn, ltefn, ltfn, comp, ecomp; + var gtfn, ltefn, ltfn, comp, ecomp switch (hilo) { case '>': - gtfn = gt; - ltefn = lte; - ltfn = lt; - comp = '>'; - ecomp = '>='; - break; + gtfn = gt + ltefn = lte + ltfn = lt + comp = '>' + ecomp = '>=' + break case '<': - gtfn = lt; - ltefn = gte; - ltfn = gt; - comp = '<'; - ecomp = '<='; - break; + gtfn = lt + ltefn = gte + ltfn = gt + comp = '<' + ecomp = '<=' + break default: - throw new TypeError('Must provide a hilo val of "<" or ">"'); + throw new TypeError('Must provide a hilo val of "<" or ">"') } // If it satisifes the range it is not outside - if (satisfies(version, range, loose)) { - return false; + if (satisfies(version, range, options)) { + return false } // From now on, variable terms are as if we're in "gtr" mode. // but note that everything is flipped for the "ltr" function. for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i]; + var comparators = range.set[i] - var high = null; - var low = null; + var high = null + var low = null - comparators.forEach(function(comparator) { + comparators.forEach(function (comparator) { if (comparator.semver === ANY) { comparator = new Comparator('>=0.0.0') } - high = high || comparator; - low = low || comparator; - if (gtfn(comparator.semver, high.semver, loose)) { - high = comparator; - } else if (ltfn(comparator.semver, low.semver, loose)) { - low = comparator; + high = high || comparator + low = low || comparator + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator } - }); + }) // If the edge version comparator has a operator then our version // isn't outside it if (high.operator === comp || high.operator === ecomp) { - return false; + return false } // If the lowest version comparator has an operator and our version // is less than it then it isn't higher than the range if ((!low.operator || low.operator === comp) && ltefn(version, low.semver)) { - return false; + return false } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false; + return false } } - return true; + return true } -exports.prerelease = prerelease; -function prerelease(version, loose) { - var parsed = parse(version, loose); - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null; +exports.prerelease = prerelease +function prerelease (version, options) { + var parsed = parse(version, options) + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null } -exports.intersects = intersects; -function intersects(r1, r2, loose) { - r1 = new Range(r1, loose) - r2 = new Range(r2, loose) +exports.intersects = intersects +function intersects (r1, r2, options) { + r1 = new Range(r1, options) + r2 = new Range(r2, options) return r1.intersects(r2) } +exports.coerce = coerce +function coerce (version) { + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null + } + + var match = version.match(re[COERCE]) + + if (match == null) { + return null + } + + return parse(match[1] + + '.' + (match[2] || '0') + + '.' + (match[3] || '0')) +} + /***/ }), /* 523 */ @@ -52531,8 +52718,8 @@ const fs = __webpack_require__(546); const writeFileAtomic = __webpack_require__(550); const sortKeys = __webpack_require__(557); const makeDir = __webpack_require__(559); -const pify = __webpack_require__(562); -const detectIndent = __webpack_require__(563); +const pify = __webpack_require__(561); +const detectIndent = __webpack_require__(562); const init = (fn, filePath, data, options) => { if (!filePath) { @@ -54607,7 +54794,7 @@ module.exports = function (x) { const fs = __webpack_require__(23); const path = __webpack_require__(16); const pify = __webpack_require__(560); -const semver = __webpack_require__(561); +const semver = __webpack_require__(522); const defaults = { mode: 0o777 & (~process.umask()), @@ -54669,1647 +54856,158 @@ const makeDir = (input, options) => Promise.resolve().then(() => { if (error.code === 'ENOENT') { if (path.dirname(pth) === pth) { throw permissionError(pth); - } - - if (error.message.includes('null bytes')) { - throw error; - } - - return make(path.dirname(pth)).then(() => make(pth)); - } - - return stat(pth) - .then(stats => stats.isDirectory() ? pth : Promise.reject()) - .catch(() => { - throw error; - }); - }); - }; - - return make(path.resolve(input)); -}); - -module.exports = makeDir; -module.exports.default = makeDir; - -module.exports.sync = (input, options) => { - checkPath(input); - options = Object.assign({}, defaults, options); - - if (useNativeRecursiveOption && options.fs.mkdirSync === fs.mkdirSync) { - const pth = path.resolve(input); - - fs.mkdirSync(pth, { - mode: options.mode, - recursive: true - }); - - return pth; - } - - const make = pth => { - try { - options.fs.mkdirSync(pth, options.mode); - } catch (error) { - if (error.code === 'EPERM') { - throw error; - } - - if (error.code === 'ENOENT') { - if (path.dirname(pth) === pth) { - throw permissionError(pth); - } - - if (error.message.includes('null bytes')) { - throw error; - } - - make(path.dirname(pth)); - return make(pth); - } - - try { - if (!options.fs.statSync(pth).isDirectory()) { - throw new Error('The path is not a directory'); - } - } catch (_) { - throw error; - } - } - - return pth; - }; - - return make(path.resolve(input)); -}; - - -/***/ }), -/* 560 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -const processFn = (fn, options) => function (...args) { - const P = options.promiseModule; - - return new P((resolve, reject) => { - if (options.multiArgs) { - args.push((...result) => { - if (options.errorFirst) { - if (result[0]) { - reject(result); - } else { - result.shift(); - resolve(result); - } - } else { - resolve(result); - } - }); - } else if (options.errorFirst) { - args.push((error, result) => { - if (error) { - reject(error); - } else { - resolve(result); - } - }); - } else { - args.push(resolve); - } - - fn.apply(this, args); - }); -}; - -module.exports = (input, options) => { - options = Object.assign({ - exclude: [/.+(Sync|Stream)$/], - errorFirst: true, - promiseModule: Promise - }, options); - - const objType = typeof input; - if (!(input !== null && (objType === 'object' || objType === 'function'))) { - throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``); - } - - const filter = key => { - const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); - return options.include ? options.include.some(match) : !options.exclude.some(match); - }; - - let ret; - if (objType === 'function') { - ret = function (...args) { - return options.excludeMain ? input(...args) : processFn(input, options).apply(this, args); - }; - } else { - ret = Object.create(Object.getPrototypeOf(input)); - } - - for (const key in input) { // eslint-disable-line guard-for-in - const property = input[key]; - ret[key] = typeof property === 'function' && filter(key) ? processFn(property, options) : property; - } - - return ret; -}; - - -/***/ }), -/* 561 */ -/***/ (function(module, exports) { - -exports = module.exports = SemVer - -var debug -/* istanbul ignore next */ -if (typeof process === 'object' && - process.env && - process.env.NODE_DEBUG && - /\bsemver\b/i.test(process.env.NODE_DEBUG)) { - debug = function () { - var args = Array.prototype.slice.call(arguments, 0) - args.unshift('SEMVER') - console.log.apply(console, args) - } -} else { - debug = function () {} -} - -// Note: this is the semver.org version of the spec that it implements -// Not necessarily the package version of this code. -exports.SEMVER_SPEC_VERSION = '2.0.0' - -var MAX_LENGTH = 256 -var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || - /* istanbul ignore next */ 9007199254740991 - -// Max safe segment length for coercion. -var MAX_SAFE_COMPONENT_LENGTH = 16 - -// The actual regexps go on exports.re -var re = exports.re = [] -var src = exports.src = [] -var R = 0 - -// The following Regular Expressions can be used for tokenizing, -// validating, and parsing SemVer version strings. - -// ## Numeric Identifier -// A single `0`, or a non-zero digit followed by zero or more digits. - -var NUMERICIDENTIFIER = R++ -src[NUMERICIDENTIFIER] = '0|[1-9]\\d*' -var NUMERICIDENTIFIERLOOSE = R++ -src[NUMERICIDENTIFIERLOOSE] = '[0-9]+' - -// ## Non-numeric Identifier -// Zero or more digits, followed by a letter or hyphen, and then zero or -// more letters, digits, or hyphens. - -var NONNUMERICIDENTIFIER = R++ -src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' - -// ## Main Version -// Three dot-separated numeric identifiers. - -var MAINVERSION = R++ -src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')' - -var MAINVERSIONLOOSE = R++ -src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')' - -// ## Pre-release Version Identifier -// A numeric identifier, or a non-numeric identifier. - -var PRERELEASEIDENTIFIER = R++ -src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + - '|' + src[NONNUMERICIDENTIFIER] + ')' - -var PRERELEASEIDENTIFIERLOOSE = R++ -src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + - '|' + src[NONNUMERICIDENTIFIER] + ')' - -// ## Pre-release Version -// Hyphen, followed by one or more dot-separated pre-release version -// identifiers. - -var PRERELEASE = R++ -src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + - '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))' - -var PRERELEASELOOSE = R++ -src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + - '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))' - -// ## Build Metadata Identifier -// Any combination of digits, letters, or hyphens. - -var BUILDIDENTIFIER = R++ -src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+' - -// ## Build Metadata -// Plus sign, followed by one or more period-separated build metadata -// identifiers. - -var BUILD = R++ -src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + - '(?:\\.' + src[BUILDIDENTIFIER] + ')*))' - -// ## Full Version String -// A main version, followed optionally by a pre-release version and -// build metadata. - -// Note that the only major, minor, patch, and pre-release sections of -// the version string are capturing groups. The build metadata is not a -// capturing group, because it should not ever be used in version -// comparison. - -var FULL = R++ -var FULLPLAIN = 'v?' + src[MAINVERSION] + - src[PRERELEASE] + '?' + - src[BUILD] + '?' - -src[FULL] = '^' + FULLPLAIN + '$' - -// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. -// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty -// common in the npm registry. -var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + - src[PRERELEASELOOSE] + '?' + - src[BUILD] + '?' - -var LOOSE = R++ -src[LOOSE] = '^' + LOOSEPLAIN + '$' - -var GTLT = R++ -src[GTLT] = '((?:<|>)?=?)' - -// Something like "2.*" or "1.2.x". -// Note that "x.x" is a valid xRange identifer, meaning "any version" -// Only the first item is strictly required. -var XRANGEIDENTIFIERLOOSE = R++ -src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' -var XRANGEIDENTIFIER = R++ -src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*' - -var XRANGEPLAIN = R++ -src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:' + src[PRERELEASE] + ')?' + - src[BUILD] + '?' + - ')?)?' - -var XRANGEPLAINLOOSE = R++ -src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:' + src[PRERELEASELOOSE] + ')?' + - src[BUILD] + '?' + - ')?)?' - -var XRANGE = R++ -src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$' -var XRANGELOOSE = R++ -src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$' - -// Coercion. -// Extract anything that could conceivably be a part of a valid semver -var COERCE = R++ -src[COERCE] = '(?:^|[^\\d])' + - '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:$|[^\\d])' - -// Tilde ranges. -// Meaning is "reasonably at or greater than" -var LONETILDE = R++ -src[LONETILDE] = '(?:~>?)' - -var TILDETRIM = R++ -src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+' -re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g') -var tildeTrimReplace = '$1~' - -var TILDE = R++ -src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$' -var TILDELOOSE = R++ -src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$' - -// Caret ranges. -// Meaning is "at least and backwards compatible with" -var LONECARET = R++ -src[LONECARET] = '(?:\\^)' - -var CARETTRIM = R++ -src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+' -re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g') -var caretTrimReplace = '$1^' - -var CARET = R++ -src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$' -var CARETLOOSE = R++ -src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$' - -// A simple gt/lt/eq thing, or just "" to indicate "any version" -var COMPARATORLOOSE = R++ -src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$' -var COMPARATOR = R++ -src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$' - -// An expression to strip any whitespace between the gtlt and the thing -// it modifies, so that `> 1.2.3` ==> `>1.2.3` -var COMPARATORTRIM = R++ -src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + - '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')' - -// this one has to use the /g flag -re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g') -var comparatorTrimReplace = '$1$2$3' - -// Something like `1.2.3 - 1.2.4` -// Note that these all use the loose form, because they'll be -// checked against either the strict or loose comparator form -// later. -var HYPHENRANGE = R++ -src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAIN] + ')' + - '\\s*$' - -var HYPHENRANGELOOSE = R++ -src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s*$' - -// Star ranges basically just allow anything at all. -var STAR = R++ -src[STAR] = '(<|>)?=?\\s*\\*' - -// Compile to actual regexp objects. -// All are flag-free, unless they were created above with a flag. -for (var i = 0; i < R; i++) { - debug(i, src[i]) - if (!re[i]) { - re[i] = new RegExp(src[i]) - } -} - -exports.parse = parse -function parse (version, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - if (version instanceof SemVer) { - return version - } - - if (typeof version !== 'string') { - return null - } - - if (version.length > MAX_LENGTH) { - return null - } - - var r = options.loose ? re[LOOSE] : re[FULL] - if (!r.test(version)) { - return null - } - - try { - return new SemVer(version, options) - } catch (er) { - return null - } -} - -exports.valid = valid -function valid (version, options) { - var v = parse(version, options) - return v ? v.version : null -} - -exports.clean = clean -function clean (version, options) { - var s = parse(version.trim().replace(/^[=v]+/, ''), options) - return s ? s.version : null -} - -exports.SemVer = SemVer - -function SemVer (version, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - if (version instanceof SemVer) { - if (version.loose === options.loose) { - return version - } else { - version = version.version - } - } else if (typeof version !== 'string') { - throw new TypeError('Invalid Version: ' + version) - } - - if (version.length > MAX_LENGTH) { - throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') - } - - if (!(this instanceof SemVer)) { - return new SemVer(version, options) - } - - debug('SemVer', version, options) - this.options = options - this.loose = !!options.loose - - var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL]) - - if (!m) { - throw new TypeError('Invalid Version: ' + version) - } - - this.raw = version - - // these are actually numbers - this.major = +m[1] - this.minor = +m[2] - this.patch = +m[3] - - if (this.major > MAX_SAFE_INTEGER || this.major < 0) { - throw new TypeError('Invalid major version') - } - - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { - throw new TypeError('Invalid minor version') - } - - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { - throw new TypeError('Invalid patch version') - } - - // numberify any prerelease numeric ids - if (!m[4]) { - this.prerelease = [] - } else { - this.prerelease = m[4].split('.').map(function (id) { - if (/^[0-9]+$/.test(id)) { - var num = +id - if (num >= 0 && num < MAX_SAFE_INTEGER) { - return num - } - } - return id - }) - } - - this.build = m[5] ? m[5].split('.') : [] - this.format() -} - -SemVer.prototype.format = function () { - this.version = this.major + '.' + this.minor + '.' + this.patch - if (this.prerelease.length) { - this.version += '-' + this.prerelease.join('.') - } - return this.version -} - -SemVer.prototype.toString = function () { - return this.version -} - -SemVer.prototype.compare = function (other) { - debug('SemVer.compare', this.version, this.options, other) - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - return this.compareMain(other) || this.comparePre(other) -} - -SemVer.prototype.compareMain = function (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - return compareIdentifiers(this.major, other.major) || - compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch) -} - -SemVer.prototype.comparePre = function (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) { - return -1 - } else if (!this.prerelease.length && other.prerelease.length) { - return 1 - } else if (!this.prerelease.length && !other.prerelease.length) { - return 0 - } - - var i = 0 - do { - var a = this.prerelease[i] - var b = other.prerelease[i] - debug('prerelease compare', i, a, b) - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue - } else { - return compareIdentifiers(a, b) - } - } while (++i) -} - -// preminor will bump the version up to the next minor release, and immediately -// down to pre-release. premajor and prepatch work the same way. -SemVer.prototype.inc = function (release, identifier) { - switch (release) { - case 'premajor': - this.prerelease.length = 0 - this.patch = 0 - this.minor = 0 - this.major++ - this.inc('pre', identifier) - break - case 'preminor': - this.prerelease.length = 0 - this.patch = 0 - this.minor++ - this.inc('pre', identifier) - break - case 'prepatch': - // If this is already a prerelease, it will bump to the next version - // drop any prereleases that might already exist, since they are not - // relevant at this point. - this.prerelease.length = 0 - this.inc('patch', identifier) - this.inc('pre', identifier) - break - // If the input is a non-prerelease version, this acts the same as - // prepatch. - case 'prerelease': - if (this.prerelease.length === 0) { - this.inc('patch', identifier) - } - this.inc('pre', identifier) - break - - case 'major': - // If this is a pre-major version, bump up to the same major version. - // Otherwise increment major. - // 1.0.0-5 bumps to 1.0.0 - // 1.1.0 bumps to 2.0.0 - if (this.minor !== 0 || - this.patch !== 0 || - this.prerelease.length === 0) { - this.major++ - } - this.minor = 0 - this.patch = 0 - this.prerelease = [] - break - case 'minor': - // If this is a pre-minor version, bump up to the same minor version. - // Otherwise increment minor. - // 1.2.0-5 bumps to 1.2.0 - // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) { - this.minor++ - } - this.patch = 0 - this.prerelease = [] - break - case 'patch': - // If this is not a pre-release version, it will increment the patch. - // If it is a pre-release it will bump up to the same patch version. - // 1.2.0-5 patches to 1.2.0 - // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) { - this.patch++ - } - this.prerelease = [] - break - // This probably shouldn't be used publicly. - // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. - case 'pre': - if (this.prerelease.length === 0) { - this.prerelease = [0] - } else { - var i = this.prerelease.length - while (--i >= 0) { - if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++ - i = -2 - } - } - if (i === -1) { - // didn't increment anything - this.prerelease.push(0) - } - } - if (identifier) { - // 1.2.0-beta.1 bumps to 1.2.0-beta.2, - // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 - if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) { - this.prerelease = [identifier, 0] - } - } else { - this.prerelease = [identifier, 0] - } - } - break - - default: - throw new Error('invalid increment argument: ' + release) - } - this.format() - this.raw = this.version - return this -} - -exports.inc = inc -function inc (version, release, loose, identifier) { - if (typeof (loose) === 'string') { - identifier = loose - loose = undefined - } - - try { - return new SemVer(version, loose).inc(release, identifier).version - } catch (er) { - return null - } -} - -exports.diff = diff -function diff (version1, version2) { - if (eq(version1, version2)) { - return null - } else { - var v1 = parse(version1) - var v2 = parse(version2) - var prefix = '' - if (v1.prerelease.length || v2.prerelease.length) { - prefix = 'pre' - var defaultResult = 'prerelease' - } - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return prefix + key - } - } - } - return defaultResult // may be undefined - } -} - -exports.compareIdentifiers = compareIdentifiers - -var numeric = /^[0-9]+$/ -function compareIdentifiers (a, b) { - var anum = numeric.test(a) - var bnum = numeric.test(b) - - if (anum && bnum) { - a = +a - b = +b - } - - return a === b ? 0 - : (anum && !bnum) ? -1 - : (bnum && !anum) ? 1 - : a < b ? -1 - : 1 -} - -exports.rcompareIdentifiers = rcompareIdentifiers -function rcompareIdentifiers (a, b) { - return compareIdentifiers(b, a) -} - -exports.major = major -function major (a, loose) { - return new SemVer(a, loose).major -} - -exports.minor = minor -function minor (a, loose) { - return new SemVer(a, loose).minor -} - -exports.patch = patch -function patch (a, loose) { - return new SemVer(a, loose).patch -} - -exports.compare = compare -function compare (a, b, loose) { - return new SemVer(a, loose).compare(new SemVer(b, loose)) -} - -exports.compareLoose = compareLoose -function compareLoose (a, b) { - return compare(a, b, true) -} - -exports.rcompare = rcompare -function rcompare (a, b, loose) { - return compare(b, a, loose) -} - -exports.sort = sort -function sort (list, loose) { - return list.sort(function (a, b) { - return exports.compare(a, b, loose) - }) -} - -exports.rsort = rsort -function rsort (list, loose) { - return list.sort(function (a, b) { - return exports.rcompare(a, b, loose) - }) -} - -exports.gt = gt -function gt (a, b, loose) { - return compare(a, b, loose) > 0 -} - -exports.lt = lt -function lt (a, b, loose) { - return compare(a, b, loose) < 0 -} - -exports.eq = eq -function eq (a, b, loose) { - return compare(a, b, loose) === 0 -} - -exports.neq = neq -function neq (a, b, loose) { - return compare(a, b, loose) !== 0 -} - -exports.gte = gte -function gte (a, b, loose) { - return compare(a, b, loose) >= 0 -} - -exports.lte = lte -function lte (a, b, loose) { - return compare(a, b, loose) <= 0 -} - -exports.cmp = cmp -function cmp (a, op, b, loose) { - switch (op) { - case '===': - if (typeof a === 'object') - a = a.version - if (typeof b === 'object') - b = b.version - return a === b - - case '!==': - if (typeof a === 'object') - a = a.version - if (typeof b === 'object') - b = b.version - return a !== b - - case '': - case '=': - case '==': - return eq(a, b, loose) - - case '!=': - return neq(a, b, loose) - - case '>': - return gt(a, b, loose) - - case '>=': - return gte(a, b, loose) - - case '<': - return lt(a, b, loose) - - case '<=': - return lte(a, b, loose) - - default: - throw new TypeError('Invalid operator: ' + op) - } -} - -exports.Comparator = Comparator -function Comparator (comp, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - if (comp instanceof Comparator) { - if (comp.loose === !!options.loose) { - return comp - } else { - comp = comp.value - } - } - - if (!(this instanceof Comparator)) { - return new Comparator(comp, options) - } - - debug('comparator', comp, options) - this.options = options - this.loose = !!options.loose - this.parse(comp) - - if (this.semver === ANY) { - this.value = '' - } else { - this.value = this.operator + this.semver.version - } - - debug('comp', this) -} - -var ANY = {} -Comparator.prototype.parse = function (comp) { - var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR] - var m = comp.match(r) - - if (!m) { - throw new TypeError('Invalid comparator: ' + comp) - } - - this.operator = m[1] - if (this.operator === '=') { - this.operator = '' - } - - // if it literally is just '>' or '' then allow anything. - if (!m[2]) { - this.semver = ANY - } else { - this.semver = new SemVer(m[2], this.options.loose) - } -} - -Comparator.prototype.toString = function () { - return this.value -} - -Comparator.prototype.test = function (version) { - debug('Comparator.test', version, this.options.loose) - - if (this.semver === ANY) { - return true - } - - if (typeof version === 'string') { - version = new SemVer(version, this.options) - } - - return cmp(version, this.operator, this.semver, this.options) -} - -Comparator.prototype.intersects = function (comp, options) { - if (!(comp instanceof Comparator)) { - throw new TypeError('a Comparator is required') - } - - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - var rangeTmp - - if (this.operator === '') { - rangeTmp = new Range(comp.value, options) - return satisfies(this.value, rangeTmp, options) - } else if (comp.operator === '') { - rangeTmp = new Range(this.value, options) - return satisfies(comp.semver, rangeTmp, options) - } - - var sameDirectionIncreasing = - (this.operator === '>=' || this.operator === '>') && - (comp.operator === '>=' || comp.operator === '>') - var sameDirectionDecreasing = - (this.operator === '<=' || this.operator === '<') && - (comp.operator === '<=' || comp.operator === '<') - var sameSemVer = this.semver.version === comp.semver.version - var differentDirectionsInclusive = - (this.operator === '>=' || this.operator === '<=') && - (comp.operator === '>=' || comp.operator === '<=') - var oppositeDirectionsLessThan = - cmp(this.semver, '<', comp.semver, options) && - ((this.operator === '>=' || this.operator === '>') && - (comp.operator === '<=' || comp.operator === '<')) - var oppositeDirectionsGreaterThan = - cmp(this.semver, '>', comp.semver, options) && - ((this.operator === '<=' || this.operator === '<') && - (comp.operator === '>=' || comp.operator === '>')) - - return sameDirectionIncreasing || sameDirectionDecreasing || - (sameSemVer && differentDirectionsInclusive) || - oppositeDirectionsLessThan || oppositeDirectionsGreaterThan -} - -exports.Range = Range -function Range (range, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - if (range instanceof Range) { - if (range.loose === !!options.loose && - range.includePrerelease === !!options.includePrerelease) { - return range - } else { - return new Range(range.raw, options) - } - } - - if (range instanceof Comparator) { - return new Range(range.value, options) - } - - if (!(this instanceof Range)) { - return new Range(range, options) - } - - this.options = options - this.loose = !!options.loose - this.includePrerelease = !!options.includePrerelease - - // First, split based on boolean or || - this.raw = range - this.set = range.split(/\s*\|\|\s*/).map(function (range) { - return this.parseRange(range.trim()) - }, this).filter(function (c) { - // throw out any that are not relevant for whatever reason - return c.length - }) - - if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + range) - } - - this.format() -} - -Range.prototype.format = function () { - this.range = this.set.map(function (comps) { - return comps.join(' ').trim() - }).join('||').trim() - return this.range -} - -Range.prototype.toString = function () { - return this.range -} - -Range.prototype.parseRange = function (range) { - var loose = this.options.loose - range = range.trim() - // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE] - range = range.replace(hr, hyphenReplace) - debug('hyphen replace', range) - // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace) - debug('comparator trim', range, re[COMPARATORTRIM]) - - // `~ 1.2.3` => `~1.2.3` - range = range.replace(re[TILDETRIM], tildeTrimReplace) - - // `^ 1.2.3` => `^1.2.3` - range = range.replace(re[CARETTRIM], caretTrimReplace) - - // normalize spaces - range = range.split(/\s+/).join(' ') - - // At this point, the range is completely trimmed and - // ready to be split into comparators. - - var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR] - var set = range.split(' ').map(function (comp) { - return parseComparator(comp, this.options) - }, this).join(' ').split(/\s+/) - if (this.options.loose) { - // in loose mode, throw out any that are not valid comparators - set = set.filter(function (comp) { - return !!comp.match(compRe) - }) - } - set = set.map(function (comp) { - return new Comparator(comp, this.options) - }, this) - - return set -} - -Range.prototype.intersects = function (range, options) { - if (!(range instanceof Range)) { - throw new TypeError('a Range is required') - } - - return this.set.some(function (thisComparators) { - return thisComparators.every(function (thisComparator) { - return range.set.some(function (rangeComparators) { - return rangeComparators.every(function (rangeComparator) { - return thisComparator.intersects(rangeComparator, options) - }) - }) - }) - }) -} - -// Mostly just for testing and legacy API reasons -exports.toComparators = toComparators -function toComparators (range, options) { - return new Range(range, options).set.map(function (comp) { - return comp.map(function (c) { - return c.value - }).join(' ').trim().split(' ') - }) -} - -// comprised of xranges, tildes, stars, and gtlt's at this point. -// already replaced the hyphen ranges -// turn into a set of JUST comparators. -function parseComparator (comp, options) { - debug('comp', comp, options) - comp = replaceCarets(comp, options) - debug('caret', comp) - comp = replaceTildes(comp, options) - debug('tildes', comp) - comp = replaceXRanges(comp, options) - debug('xrange', comp) - comp = replaceStars(comp, options) - debug('stars', comp) - return comp -} - -function isX (id) { - return !id || id.toLowerCase() === 'x' || id === '*' -} - -// ~, ~> --> * (any, kinda silly) -// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 -// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 -// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 -// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 -// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 -function replaceTildes (comp, options) { - return comp.trim().split(/\s+/).map(function (comp) { - return replaceTilde(comp, options) - }).join(' ') -} - -function replaceTilde (comp, options) { - var r = options.loose ? re[TILDELOOSE] : re[TILDE] - return comp.replace(r, function (_, M, m, p, pr) { - debug('tilde', comp, _, M, m, p, pr) - var ret - - if (isX(M)) { - ret = '' - } else if (isX(m)) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (isX(p)) { - // ~1.2 == >=1.2.0 <1.3.0 - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } else if (pr) { - debug('replaceTilde pr', pr) - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + (+m + 1) + '.0' - } else { - // ~1.2.3 == >=1.2.3 <1.3.0 - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0' - } - - debug('tilde return', ret) - return ret - }) -} - -// ^ --> * (any, kinda silly) -// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 -// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 -// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 -// ^1.2.3 --> >=1.2.3 <2.0.0 -// ^1.2.0 --> >=1.2.0 <2.0.0 -function replaceCarets (comp, options) { - return comp.trim().split(/\s+/).map(function (comp) { - return replaceCaret(comp, options) - }).join(' ') -} - -function replaceCaret (comp, options) { - debug('caret', comp, options) - var r = options.loose ? re[CARETLOOSE] : re[CARET] - return comp.replace(r, function (_, M, m, p, pr) { - debug('caret', comp, _, M, m, p, pr) - var ret - - if (isX(M)) { - ret = '' - } else if (isX(m)) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (isX(p)) { - if (M === '0') { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } else { - ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' - } - } else if (pr) { - debug('replaceCaret pr', pr) - if (M === '0') { - if (m === '0') { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + m + '.' + (+p + 1) - } else { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + (+m + 1) + '.0' - } - } else { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + (+M + 1) + '.0.0' - } - } else { - debug('no pr') - if (M === '0') { - if (m === '0') { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + m + '.' + (+p + 1) - } else { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0' - } - } else { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + (+M + 1) + '.0.0' - } - } - - debug('caret return', ret) - return ret - }) -} - -function replaceXRanges (comp, options) { - debug('replaceXRanges', comp, options) - return comp.split(/\s+/).map(function (comp) { - return replaceXRange(comp, options) - }).join(' ') -} - -function replaceXRange (comp, options) { - comp = comp.trim() - var r = options.loose ? re[XRANGELOOSE] : re[XRANGE] - return comp.replace(r, function (ret, gtlt, M, m, p, pr) { - debug('xRange', comp, ret, gtlt, M, m, p, pr) - var xM = isX(M) - var xm = xM || isX(m) - var xp = xm || isX(p) - var anyX = xp - - if (gtlt === '=' && anyX) { - gtlt = '' - } - - if (xM) { - if (gtlt === '>' || gtlt === '<') { - // nothing is allowed - ret = '<0.0.0' - } else { - // nothing is forbidden - ret = '*' - } - } else if (gtlt && anyX) { - // we know patch is an x, because we have any x at all. - // replace X with 0 - if (xm) { - m = 0 - } - p = 0 - - if (gtlt === '>') { - // >1 => >=2.0.0 - // >1.2 => >=1.3.0 - // >1.2.3 => >= 1.2.4 - gtlt = '>=' - if (xm) { - M = +M + 1 - m = 0 - p = 0 - } else { - m = +m + 1 - p = 0 - } - } else if (gtlt === '<=') { - // <=0.7.x is actually <0.8.0, since any 0.7.x should - // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<' - if (xm) { - M = +M + 1 - } else { - m = +m + 1 - } - } - - ret = gtlt + M + '.' + m + '.' + p - } else if (xm) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (xp) { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } - - debug('xRange return', ret) - - return ret - }) -} - -// Because * is AND-ed with everything else in the comparator, -// and '' means "any version", just remove the *s entirely. -function replaceStars (comp, options) { - debug('replaceStars', comp, options) - // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(re[STAR], '') -} - -// This function is passed to string.replace(re[HYPHENRANGE]) -// M, m, patch, prerelease, build -// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 -// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do -// 1.2 - 3.4 => >=1.2.0 <3.5.0 -function hyphenReplace ($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr, tb) { - if (isX(fM)) { - from = '' - } else if (isX(fm)) { - from = '>=' + fM + '.0.0' - } else if (isX(fp)) { - from = '>=' + fM + '.' + fm + '.0' - } else { - from = '>=' + from - } - - if (isX(tM)) { - to = '' - } else if (isX(tm)) { - to = '<' + (+tM + 1) + '.0.0' - } else if (isX(tp)) { - to = '<' + tM + '.' + (+tm + 1) + '.0' - } else if (tpr) { - to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr - } else { - to = '<=' + to - } - - return (from + ' ' + to).trim() -} - -// if ANY of the sets match ALL of its comparators, then pass -Range.prototype.test = function (version) { - if (!version) { - return false - } - - if (typeof version === 'string') { - version = new SemVer(version, this.options) - } - - for (var i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version, this.options)) { - return true - } - } - return false -} - -function testSet (set, version, options) { - for (var i = 0; i < set.length; i++) { - if (!set[i].test(version)) { - return false - } - } - - if (version.prerelease.length && !options.includePrerelease) { - // Find the set of versions that are allowed to have prereleases - // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 - // That should allow `1.2.3-pr.2` to pass. - // However, `1.2.4-alpha.notready` should NOT be allowed, - // even though it's within the range set by the comparators. - for (i = 0; i < set.length; i++) { - debug(set[i].semver) - if (set[i].semver === ANY) { - continue - } - - if (set[i].semver.prerelease.length > 0) { - var allowed = set[i].semver - if (allowed.major === version.major && - allowed.minor === version.minor && - allowed.patch === version.patch) { - return true - } - } - } - - // Version has a -pre, but it's not one of the ones we like. - return false - } - - return true -} - -exports.satisfies = satisfies -function satisfies (version, range, options) { - try { - range = new Range(range, options) - } catch (er) { - return false - } - return range.test(version) -} - -exports.maxSatisfying = maxSatisfying -function maxSatisfying (versions, range, options) { - var max = null - var maxSV = null - try { - var rangeObj = new Range(range, options) - } catch (er) { - return null - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!max || maxSV.compare(v) === -1) { - // compare(max, v, true) - max = v - maxSV = new SemVer(max, options) - } - } - }) - return max -} - -exports.minSatisfying = minSatisfying -function minSatisfying (versions, range, options) { - var min = null - var minSV = null - try { - var rangeObj = new Range(range, options) - } catch (er) { - return null - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!min || minSV.compare(v) === 1) { - // compare(min, v, true) - min = v - minSV = new SemVer(min, options) - } - } - }) - return min -} + } -exports.minVersion = minVersion -function minVersion (range, loose) { - range = new Range(range, loose) + if (error.message.includes('null bytes')) { + throw error; + } - var minver = new SemVer('0.0.0') - if (range.test(minver)) { - return minver - } + return make(path.dirname(pth)).then(() => make(pth)); + } - minver = new SemVer('0.0.0-0') - if (range.test(minver)) { - return minver - } + return stat(pth) + .then(stats => stats.isDirectory() ? pth : Promise.reject()) + .catch(() => { + throw error; + }); + }); + }; - minver = null - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i] + return make(path.resolve(input)); +}); - comparators.forEach(function (comparator) { - // Clone to avoid manipulating the comparator's semver object. - var compver = new SemVer(comparator.semver.version) - switch (comparator.operator) { - case '>': - if (compver.prerelease.length === 0) { - compver.patch++ - } else { - compver.prerelease.push(0) - } - compver.raw = compver.format() - /* fallthrough */ - case '': - case '>=': - if (!minver || gt(minver, compver)) { - minver = compver - } - break - case '<': - case '<=': - /* Ignore maximum versions */ - break - /* istanbul ignore next */ - default: - throw new Error('Unexpected operation: ' + comparator.operator) - } - }) - } +module.exports = makeDir; +module.exports.default = makeDir; - if (minver && range.test(minver)) { - return minver - } +module.exports.sync = (input, options) => { + checkPath(input); + options = Object.assign({}, defaults, options); - return null -} + if (useNativeRecursiveOption && options.fs.mkdirSync === fs.mkdirSync) { + const pth = path.resolve(input); -exports.validRange = validRange -function validRange (range, options) { - try { - // Return '*' instead of '' so that truthiness works. - // This will throw if it's invalid anyway - return new Range(range, options).range || '*' - } catch (er) { - return null - } -} + fs.mkdirSync(pth, { + mode: options.mode, + recursive: true + }); -// Determine if version is less than all the versions possible in the range -exports.ltr = ltr -function ltr (version, range, options) { - return outside(version, range, '<', options) -} + return pth; + } -// Determine if version is greater than all the versions possible in the range. -exports.gtr = gtr -function gtr (version, range, options) { - return outside(version, range, '>', options) -} + const make = pth => { + try { + options.fs.mkdirSync(pth, options.mode); + } catch (error) { + if (error.code === 'EPERM') { + throw error; + } -exports.outside = outside -function outside (version, range, hilo, options) { - version = new SemVer(version, options) - range = new Range(range, options) + if (error.code === 'ENOENT') { + if (path.dirname(pth) === pth) { + throw permissionError(pth); + } - var gtfn, ltefn, ltfn, comp, ecomp - switch (hilo) { - case '>': - gtfn = gt - ltefn = lte - ltfn = lt - comp = '>' - ecomp = '>=' - break - case '<': - gtfn = lt - ltefn = gte - ltfn = gt - comp = '<' - ecomp = '<=' - break - default: - throw new TypeError('Must provide a hilo val of "<" or ">"') - } + if (error.message.includes('null bytes')) { + throw error; + } - // If it satisifes the range it is not outside - if (satisfies(version, range, options)) { - return false - } + make(path.dirname(pth)); + return make(pth); + } - // From now on, variable terms are as if we're in "gtr" mode. - // but note that everything is flipped for the "ltr" function. + try { + if (!options.fs.statSync(pth).isDirectory()) { + throw new Error('The path is not a directory'); + } + } catch (_) { + throw error; + } + } - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i] + return pth; + }; - var high = null - var low = null + return make(path.resolve(input)); +}; - comparators.forEach(function (comparator) { - if (comparator.semver === ANY) { - comparator = new Comparator('>=0.0.0') - } - high = high || comparator - low = low || comparator - if (gtfn(comparator.semver, high.semver, options)) { - high = comparator - } else if (ltfn(comparator.semver, low.semver, options)) { - low = comparator - } - }) - // If the edge version comparator has a operator then our version - // isn't outside it - if (high.operator === comp || high.operator === ecomp) { - return false - } +/***/ }), +/* 560 */ +/***/ (function(module, exports, __webpack_require__) { - // If the lowest version comparator has an operator and our version - // is less than it then it isn't higher than the range - if ((!low.operator || low.operator === comp) && - ltefn(version, low.semver)) { - return false - } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false - } - } - return true -} +"use strict"; -exports.prerelease = prerelease -function prerelease (version, options) { - var parsed = parse(version, options) - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null -} -exports.intersects = intersects -function intersects (r1, r2, options) { - r1 = new Range(r1, options) - r2 = new Range(r2, options) - return r1.intersects(r2) -} +const processFn = (fn, options) => function (...args) { + const P = options.promiseModule; -exports.coerce = coerce -function coerce (version) { - if (version instanceof SemVer) { - return version - } + return new P((resolve, reject) => { + if (options.multiArgs) { + args.push((...result) => { + if (options.errorFirst) { + if (result[0]) { + reject(result); + } else { + result.shift(); + resolve(result); + } + } else { + resolve(result); + } + }); + } else if (options.errorFirst) { + args.push((error, result) => { + if (error) { + reject(error); + } else { + resolve(result); + } + }); + } else { + args.push(resolve); + } - if (typeof version !== 'string') { - return null - } + fn.apply(this, args); + }); +}; - var match = version.match(re[COERCE]) +module.exports = (input, options) => { + options = Object.assign({ + exclude: [/.+(Sync|Stream)$/], + errorFirst: true, + promiseModule: Promise + }, options); - if (match == null) { - return null - } + const objType = typeof input; + if (!(input !== null && (objType === 'object' || objType === 'function'))) { + throw new TypeError(`Expected \`input\` to be a \`Function\` or \`Object\`, got \`${input === null ? 'null' : objType}\``); + } - return parse(match[1] + - '.' + (match[2] || '0') + - '.' + (match[3] || '0')) -} + const filter = key => { + const match = pattern => typeof pattern === 'string' ? key === pattern : pattern.test(key); + return options.include ? options.include.some(match) : !options.exclude.some(match); + }; + + let ret; + if (objType === 'function') { + ret = function (...args) { + return options.excludeMain ? input(...args) : processFn(input, options).apply(this, args); + }; + } else { + ret = Object.create(Object.getPrototypeOf(input)); + } + + for (const key in input) { // eslint-disable-line guard-for-in + const property = input[key]; + ret[key] = typeof property === 'function' && filter(key) ? processFn(property, options) : property; + } + + return ret; +}; /***/ }), -/* 562 */ +/* 561 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56384,7 +55082,7 @@ module.exports = (input, options) => { /***/ }), -/* 563 */ +/* 562 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -56513,7 +55211,7 @@ module.exports = str => { /***/ }), -/* 564 */ +/* 563 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56522,7 +55220,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackage", function() { return runScriptInPackage; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runScriptInPackageStreaming", function() { return runScriptInPackageStreaming; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "yarnWorkspacesInfo", function() { return yarnWorkspacesInfo; }); -/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(565); +/* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(564); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -56592,7 +55290,7 @@ async function yarnWorkspacesInfo(directory) { } /***/ }), -/* 565 */ +/* 564 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56603,9 +55301,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(351); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(566); +/* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(565); /* harmony import */ var log_symbols__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(log_symbols__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(571); +/* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(570); /* harmony import */ var strong_log_transformer__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(strong_log_transformer__WEBPACK_IMPORTED_MODULE_3__); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } @@ -56671,12 +55369,12 @@ function spawnStreaming(command, args, opts, { } /***/ }), -/* 566 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(567); +const chalk = __webpack_require__(566); const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color'; @@ -56698,16 +55396,16 @@ module.exports = isSupported ? main : fallbacks; /***/ }), -/* 567 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(568); -const stdoutColor = __webpack_require__(569).stdout; +const ansiStyles = __webpack_require__(567); +const stdoutColor = __webpack_require__(568).stdout; -const template = __webpack_require__(570); +const template = __webpack_require__(569); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -56933,7 +55631,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 568 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57106,7 +55804,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 569 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57248,7 +55946,7 @@ module.exports = { /***/ }), -/* 570 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57383,7 +56081,7 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 571 */ +/* 570 */ /***/ (function(module, exports, __webpack_require__) { // Copyright IBM Corp. 2014,2018. All Rights Reserved. @@ -57391,12 +56089,12 @@ module.exports = (chalk, tmp) => { // This file is licensed under the Apache License 2.0. // License text available at https://opensource.org/licenses/Apache-2.0 -module.exports = __webpack_require__(572); -module.exports.cli = __webpack_require__(576); +module.exports = __webpack_require__(571); +module.exports.cli = __webpack_require__(575); /***/ }), -/* 572 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57411,9 +56109,9 @@ var stream = __webpack_require__(27); var util = __webpack_require__(29); var fs = __webpack_require__(23); -var through = __webpack_require__(573); -var duplexer = __webpack_require__(574); -var StringDecoder = __webpack_require__(575).StringDecoder; +var through = __webpack_require__(572); +var duplexer = __webpack_require__(573); +var StringDecoder = __webpack_require__(574).StringDecoder; module.exports = Logger; @@ -57602,7 +56300,7 @@ function lineMerger(host) { /***/ }), -/* 573 */ +/* 572 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(27) @@ -57716,7 +56414,7 @@ function through (write, end, opts) { /***/ }), -/* 574 */ +/* 573 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(27) @@ -57809,13 +56507,13 @@ function duplex(writer, reader) { /***/ }), -/* 575 */ +/* 574 */ /***/ (function(module, exports) { module.exports = require("string_decoder"); /***/ }), -/* 576 */ +/* 575 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -57826,11 +56524,11 @@ module.exports = require("string_decoder"); -var minimist = __webpack_require__(577); +var minimist = __webpack_require__(576); var path = __webpack_require__(16); -var Logger = __webpack_require__(572); -var pkg = __webpack_require__(578); +var Logger = __webpack_require__(571); +var pkg = __webpack_require__(577); module.exports = cli; @@ -57884,7 +56582,7 @@ function usage($0, p) { /***/ }), -/* 577 */ +/* 576 */ /***/ (function(module, exports) { module.exports = function (args, opts) { @@ -58126,13 +56824,13 @@ function isNumber (x) { /***/ }), -/* 578 */ +/* 577 */ /***/ (function(module) { module.exports = JSON.parse("{\"name\":\"strong-log-transformer\",\"version\":\"2.1.0\",\"description\":\"Stream transformer that prefixes lines with timestamps and other things.\",\"author\":\"Ryan Graham \",\"license\":\"Apache-2.0\",\"repository\":{\"type\":\"git\",\"url\":\"git://github.com/strongloop/strong-log-transformer\"},\"keywords\":[\"logging\",\"streams\"],\"bugs\":{\"url\":\"https://github.com/strongloop/strong-log-transformer/issues\"},\"homepage\":\"https://github.com/strongloop/strong-log-transformer\",\"directories\":{\"test\":\"test\"},\"bin\":{\"sl-log-transformer\":\"bin/sl-log-transformer.js\"},\"main\":\"index.js\",\"scripts\":{\"test\":\"tap --100 test/test-*\"},\"dependencies\":{\"duplexer\":\"^0.1.1\",\"minimist\":\"^1.2.0\",\"through\":\"^2.3.4\"},\"devDependencies\":{\"tap\":\"^12.0.1\"},\"engines\":{\"node\":\">=4\"}}"); /***/ }), -/* 579 */ +/* 578 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58145,7 +56843,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(580); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(579); /* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); /* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(517); /* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(501); @@ -58240,7 +56938,7 @@ function packagesFromGlobPattern({ } /***/ }), -/* 580 */ +/* 579 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58309,7 +57007,7 @@ function getProjectPaths({ } /***/ }), -/* 581 */ +/* 580 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58317,13 +57015,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getAllChecksums", function() { return getAllChecksums; }); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(23); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(582); +/* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(581); /* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); /* harmony import */ var util__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(util__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(351); /* harmony import */ var execa__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(execa__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(583); +/* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(582); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -58540,19 +57238,19 @@ async function getAllChecksums(kbn, log) { } /***/ }), -/* 582 */ +/* 581 */ /***/ (function(module, exports) { module.exports = require("crypto"); /***/ }), -/* 583 */ +/* 582 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "readYarnLock", function() { return readYarnLock; }); -/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(584); +/* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(583); /* harmony import */ var _yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_yarnpkg_lockfile__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20); /* @@ -58596,7 +57294,7 @@ async function readYarnLock(kbn) { } /***/ }), -/* 584 */ +/* 583 */ /***/ (function(module, exports, __webpack_require__) { module.exports = @@ -60155,7 +58853,7 @@ module.exports = invariant; /* 9 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(582); +module.exports = __webpack_require__(581); /***/ }), /* 10 */, @@ -62479,7 +61177,7 @@ function onceStrict (fn) { /* 63 */ /***/ (function(module, exports) { -module.exports = __webpack_require__(585); +module.exports = __webpack_require__(584); /***/ }), /* 64 */, @@ -68874,13 +67572,13 @@ module.exports = process && support(supportLevel); /******/ ]); /***/ }), -/* 585 */ +/* 584 */ /***/ (function(module, exports) { module.exports = require("buffer"); /***/ }), -/* 586 */ +/* 585 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -68977,7 +67675,7 @@ class BootstrapCacheFile { } /***/ }), -/* 587 */ +/* 586 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -68985,9 +67683,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CleanCommand", function() { return CleanCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(588); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(587); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(676); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(675); /* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); @@ -69087,21 +67785,21 @@ const CleanCommand = { }; /***/ }), -/* 588 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(29); const path = __webpack_require__(16); -const globby = __webpack_require__(589); -const isGlob = __webpack_require__(606); -const slash = __webpack_require__(667); +const globby = __webpack_require__(588); +const isGlob = __webpack_require__(605); +const slash = __webpack_require__(666); const gracefulFs = __webpack_require__(22); -const isPathCwd = __webpack_require__(669); -const isPathInside = __webpack_require__(670); -const rimraf = __webpack_require__(671); -const pMap = __webpack_require__(672); +const isPathCwd = __webpack_require__(668); +const isPathInside = __webpack_require__(669); +const rimraf = __webpack_require__(670); +const pMap = __webpack_require__(671); const rimrafP = promisify(rimraf); @@ -69215,19 +67913,19 @@ module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options /***/ }), -/* 589 */ +/* 588 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const arrayUnion = __webpack_require__(590); -const merge2 = __webpack_require__(591); -const glob = __webpack_require__(592); -const fastGlob = __webpack_require__(597); -const dirGlob = __webpack_require__(663); -const gitignore = __webpack_require__(665); -const {FilterStream, UniqueStream} = __webpack_require__(668); +const arrayUnion = __webpack_require__(589); +const merge2 = __webpack_require__(590); +const glob = __webpack_require__(591); +const fastGlob = __webpack_require__(596); +const dirGlob = __webpack_require__(662); +const gitignore = __webpack_require__(664); +const {FilterStream, UniqueStream} = __webpack_require__(667); const DEFAULT_FILTER = () => false; @@ -69400,7 +68098,7 @@ module.exports.gitignore = gitignore; /***/ }), -/* 590 */ +/* 589 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69412,7 +68110,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 591 */ +/* 590 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69526,7 +68224,7 @@ function pauseStreams (streams, options) { /***/ }), -/* 592 */ +/* 591 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -69575,13 +68273,13 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(503) var minimatch = __webpack_require__(505) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(593) +var inherits = __webpack_require__(592) var EE = __webpack_require__(379).EventEmitter var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(511) -var globSync = __webpack_require__(595) -var common = __webpack_require__(596) +var globSync = __webpack_require__(594) +var common = __webpack_require__(595) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -70322,7 +69020,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 593 */ +/* 592 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -70332,12 +69030,12 @@ try { module.exports = util.inherits; } catch (e) { /* istanbul ignore next */ - module.exports = __webpack_require__(594); + module.exports = __webpack_require__(593); } /***/ }), -/* 594 */ +/* 593 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -70370,7 +69068,7 @@ if (typeof Object.create === 'function') { /***/ }), -/* 595 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync @@ -70380,12 +69078,12 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(503) var minimatch = __webpack_require__(505) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(592).Glob +var Glob = __webpack_require__(591).Glob var util = __webpack_require__(29) var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(511) -var common = __webpack_require__(596) +var common = __webpack_require__(595) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -70862,7 +69560,7 @@ GlobSync.prototype._makeAbs = function (f) { /***/ }), -/* 596 */ +/* 595 */ /***/ (function(module, exports, __webpack_require__) { exports.alphasort = alphasort @@ -71108,17 +69806,17 @@ function childrenIgnored (self, path) { /***/ }), -/* 597 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const taskManager = __webpack_require__(598); -const async_1 = __webpack_require__(626); -const stream_1 = __webpack_require__(659); -const sync_1 = __webpack_require__(660); -const settings_1 = __webpack_require__(662); -const utils = __webpack_require__(599); +const taskManager = __webpack_require__(597); +const async_1 = __webpack_require__(625); +const stream_1 = __webpack_require__(658); +const sync_1 = __webpack_require__(659); +const settings_1 = __webpack_require__(661); +const utils = __webpack_require__(598); function FastGlob(source, options) { try { assertPatternsInput(source); @@ -71176,13 +69874,13 @@ module.exports = FastGlob; /***/ }), -/* 598 */ +/* 597 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(599); +const utils = __webpack_require__(598); function generate(patterns, settings) { const positivePatterns = getPositivePatterns(patterns); const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore); @@ -71250,28 +69948,28 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 599 */ +/* 598 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const array = __webpack_require__(600); +const array = __webpack_require__(599); exports.array = array; -const errno = __webpack_require__(601); +const errno = __webpack_require__(600); exports.errno = errno; -const fs = __webpack_require__(602); +const fs = __webpack_require__(601); exports.fs = fs; -const path = __webpack_require__(603); +const path = __webpack_require__(602); exports.path = path; -const pattern = __webpack_require__(604); +const pattern = __webpack_require__(603); exports.pattern = pattern; -const stream = __webpack_require__(625); +const stream = __webpack_require__(624); exports.stream = stream; /***/ }), -/* 600 */ +/* 599 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71284,7 +69982,7 @@ exports.flatten = flatten; /***/ }), -/* 601 */ +/* 600 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71297,7 +69995,7 @@ exports.isEnoentCodeError = isEnoentCodeError; /***/ }), -/* 602 */ +/* 601 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71322,7 +70020,7 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 603 */ +/* 602 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71343,16 +70041,16 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 604 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const globParent = __webpack_require__(605); -const isGlob = __webpack_require__(606); -const micromatch = __webpack_require__(608); +const globParent = __webpack_require__(604); +const isGlob = __webpack_require__(605); +const micromatch = __webpack_require__(607); const GLOBSTAR = '**'; function isStaticPattern(pattern) { return !isDynamicPattern(pattern); @@ -71441,13 +70139,13 @@ exports.matchAny = matchAny; /***/ }), -/* 605 */ +/* 604 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isGlob = __webpack_require__(606); +var isGlob = __webpack_require__(605); var pathPosixDirname = __webpack_require__(16).posix.dirname; var isWin32 = __webpack_require__(11).platform() === 'win32'; @@ -71482,7 +70180,7 @@ module.exports = function globParent(str) { /***/ }), -/* 606 */ +/* 605 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -71492,7 +70190,7 @@ module.exports = function globParent(str) { * Released under the MIT License. */ -var isExtglob = __webpack_require__(607); +var isExtglob = __webpack_require__(606); var chars = { '{': '}', '(': ')', '[': ']'}; var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/; var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/; @@ -71536,7 +70234,7 @@ module.exports = function isGlob(str, options) { /***/ }), -/* 607 */ +/* 606 */ /***/ (function(module, exports) { /*! @@ -71562,16 +70260,16 @@ module.exports = function isExtglob(str) { /***/ }), -/* 608 */ +/* 607 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const util = __webpack_require__(29); -const braces = __webpack_require__(609); -const picomatch = __webpack_require__(619); -const utils = __webpack_require__(622); +const braces = __webpack_require__(608); +const picomatch = __webpack_require__(618); +const utils = __webpack_require__(621); const isEmptyString = val => typeof val === 'string' && (val === '' || val === './'); /** @@ -72036,16 +70734,16 @@ module.exports = micromatch; /***/ }), -/* 609 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringify = __webpack_require__(610); -const compile = __webpack_require__(612); -const expand = __webpack_require__(616); -const parse = __webpack_require__(617); +const stringify = __webpack_require__(609); +const compile = __webpack_require__(611); +const expand = __webpack_require__(615); +const parse = __webpack_require__(616); /** * Expand the given pattern or create a regex-compatible string. @@ -72213,13 +70911,13 @@ module.exports = braces; /***/ }), -/* 610 */ +/* 609 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(611); +const utils = __webpack_require__(610); module.exports = (ast, options = {}) => { let stringify = (node, parent = {}) => { @@ -72252,7 +70950,7 @@ module.exports = (ast, options = {}) => { /***/ }), -/* 611 */ +/* 610 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72371,14 +71069,14 @@ exports.flatten = (...args) => { /***/ }), -/* 612 */ +/* 611 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fill = __webpack_require__(613); -const utils = __webpack_require__(611); +const fill = __webpack_require__(612); +const utils = __webpack_require__(610); const compile = (ast, options = {}) => { let walk = (node, parent = {}) => { @@ -72435,7 +71133,7 @@ module.exports = compile; /***/ }), -/* 613 */ +/* 612 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72449,7 +71147,7 @@ module.exports = compile; const util = __webpack_require__(29); -const toRegexRange = __webpack_require__(614); +const toRegexRange = __webpack_require__(613); const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); @@ -72691,7 +71389,7 @@ module.exports = fill; /***/ }), -/* 614 */ +/* 613 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72704,7 +71402,7 @@ module.exports = fill; -const isNumber = __webpack_require__(615); +const isNumber = __webpack_require__(614); const toRegexRange = (min, max, options) => { if (isNumber(min) === false) { @@ -72986,7 +71684,7 @@ module.exports = toRegexRange; /***/ }), -/* 615 */ +/* 614 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73011,15 +71709,15 @@ module.exports = function(num) { /***/ }), -/* 616 */ +/* 615 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const fill = __webpack_require__(613); -const stringify = __webpack_require__(610); -const utils = __webpack_require__(611); +const fill = __webpack_require__(612); +const stringify = __webpack_require__(609); +const utils = __webpack_require__(610); const append = (queue = '', stash = '', enclose = false) => { let result = []; @@ -73131,13 +71829,13 @@ module.exports = expand; /***/ }), -/* 617 */ +/* 616 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringify = __webpack_require__(610); +const stringify = __webpack_require__(609); /** * Constants @@ -73159,7 +71857,7 @@ const { CHAR_SINGLE_QUOTE, /* ' */ CHAR_NO_BREAK_SPACE, CHAR_ZERO_WIDTH_NOBREAK_SPACE -} = __webpack_require__(618); +} = __webpack_require__(617); /** * parse @@ -73471,7 +72169,7 @@ module.exports = parse; /***/ }), -/* 618 */ +/* 617 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73535,26 +72233,26 @@ module.exports = { /***/ }), -/* 619 */ +/* 618 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(620); +module.exports = __webpack_require__(619); /***/ }), -/* 620 */ +/* 619 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const scan = __webpack_require__(621); -const parse = __webpack_require__(624); -const utils = __webpack_require__(622); +const scan = __webpack_require__(620); +const parse = __webpack_require__(623); +const utils = __webpack_require__(621); /** * Creates a matcher function from one or more glob patterns. The @@ -73857,7 +72555,7 @@ picomatch.toRegex = (source, options) => { * @return {Object} */ -picomatch.constants = __webpack_require__(623); +picomatch.constants = __webpack_require__(622); /** * Expose "picomatch" @@ -73867,13 +72565,13 @@ module.exports = picomatch; /***/ }), -/* 621 */ +/* 620 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(622); +const utils = __webpack_require__(621); const { CHAR_ASTERISK, /* * */ @@ -73891,7 +72589,7 @@ const { CHAR_RIGHT_CURLY_BRACE, /* } */ CHAR_RIGHT_PARENTHESES, /* ) */ CHAR_RIGHT_SQUARE_BRACKET /* ] */ -} = __webpack_require__(623); +} = __webpack_require__(622); const isPathSeparator = code => { return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; @@ -74093,7 +72791,7 @@ module.exports = (input, options) => { /***/ }), -/* 622 */ +/* 621 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74105,7 +72803,7 @@ const { REGEX_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_GLOBAL, REGEX_REMOVE_BACKSLASH -} = __webpack_require__(623); +} = __webpack_require__(622); exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); @@ -74143,7 +72841,7 @@ exports.escapeLast = (input, char, lastIdx) => { /***/ }), -/* 623 */ +/* 622 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74329,14 +73027,14 @@ module.exports = { /***/ }), -/* 624 */ +/* 623 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(622); -const constants = __webpack_require__(623); +const utils = __webpack_require__(621); +const constants = __webpack_require__(622); /** * Constants @@ -75347,13 +74045,13 @@ module.exports = parse; /***/ }), -/* 625 */ +/* 624 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const merge2 = __webpack_require__(591); +const merge2 = __webpack_require__(590); function merge(streams) { const mergedStream = merge2(streams); streams.forEach((stream) => { @@ -75365,14 +74063,14 @@ exports.merge = merge; /***/ }), -/* 626 */ +/* 625 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(627); -const provider_1 = __webpack_require__(654); +const stream_1 = __webpack_require__(626); +const provider_1 = __webpack_require__(653); class ProviderAsync extends provider_1.default { constructor() { super(...arguments); @@ -75400,16 +74098,16 @@ exports.default = ProviderAsync; /***/ }), -/* 627 */ +/* 626 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const fsStat = __webpack_require__(628); -const fsWalk = __webpack_require__(633); -const reader_1 = __webpack_require__(653); +const fsStat = __webpack_require__(627); +const fsWalk = __webpack_require__(632); +const reader_1 = __webpack_require__(652); class ReaderStream extends reader_1.default { constructor() { super(...arguments); @@ -75462,15 +74160,15 @@ exports.default = ReaderStream; /***/ }), -/* 628 */ +/* 627 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(629); -const sync = __webpack_require__(630); -const settings_1 = __webpack_require__(631); +const async = __webpack_require__(628); +const sync = __webpack_require__(629); +const settings_1 = __webpack_require__(630); exports.Settings = settings_1.default; function stat(path, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -75493,7 +74191,7 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 629 */ +/* 628 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75531,7 +74229,7 @@ function callSuccessCallback(callback, result) { /***/ }), -/* 630 */ +/* 629 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75560,13 +74258,13 @@ exports.read = read; /***/ }), -/* 631 */ +/* 630 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(632); +const fs = __webpack_require__(631); class Settings { constructor(_options = {}) { this._options = _options; @@ -75583,7 +74281,7 @@ exports.default = Settings; /***/ }), -/* 632 */ +/* 631 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75606,16 +74304,16 @@ exports.createFileSystemAdapter = createFileSystemAdapter; /***/ }), -/* 633 */ +/* 632 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(634); -const stream_1 = __webpack_require__(649); -const sync_1 = __webpack_require__(650); -const settings_1 = __webpack_require__(652); +const async_1 = __webpack_require__(633); +const stream_1 = __webpack_require__(648); +const sync_1 = __webpack_require__(649); +const settings_1 = __webpack_require__(651); exports.Settings = settings_1.default; function walk(dir, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -75645,13 +74343,13 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 634 */ +/* 633 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async_1 = __webpack_require__(635); +const async_1 = __webpack_require__(634); class AsyncProvider { constructor(_root, _settings) { this._root = _root; @@ -75682,17 +74380,17 @@ function callSuccessCallback(callback, entries) { /***/ }), -/* 635 */ +/* 634 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const events_1 = __webpack_require__(379); -const fsScandir = __webpack_require__(636); -const fastq = __webpack_require__(645); -const common = __webpack_require__(647); -const reader_1 = __webpack_require__(648); +const fsScandir = __webpack_require__(635); +const fastq = __webpack_require__(644); +const common = __webpack_require__(646); +const reader_1 = __webpack_require__(647); class AsyncReader extends reader_1.default { constructor(_root, _settings) { super(_root, _settings); @@ -75782,15 +74480,15 @@ exports.default = AsyncReader; /***/ }), -/* 636 */ +/* 635 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const async = __webpack_require__(637); -const sync = __webpack_require__(642); -const settings_1 = __webpack_require__(643); +const async = __webpack_require__(636); +const sync = __webpack_require__(641); +const settings_1 = __webpack_require__(642); exports.Settings = settings_1.default; function scandir(path, optionsOrSettingsOrCallback, callback) { if (typeof optionsOrSettingsOrCallback === 'function') { @@ -75813,16 +74511,16 @@ function getSettings(settingsOrOptions = {}) { /***/ }), -/* 637 */ +/* 636 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(628); -const rpl = __webpack_require__(638); -const constants_1 = __webpack_require__(639); -const utils = __webpack_require__(640); +const fsStat = __webpack_require__(627); +const rpl = __webpack_require__(637); +const constants_1 = __webpack_require__(638); +const utils = __webpack_require__(639); function read(dir, settings, callback) { if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { return readdirWithFileTypes(dir, settings, callback); @@ -75911,7 +74609,7 @@ function callSuccessCallback(callback, result) { /***/ }), -/* 638 */ +/* 637 */ /***/ (function(module, exports) { module.exports = runParallel @@ -75965,7 +74663,7 @@ function runParallel (tasks, cb) { /***/ }), -/* 639 */ +/* 638 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75981,18 +74679,18 @@ exports.IS_SUPPORT_READDIR_WITH_FILE_TYPES = MAJOR_VERSION > 10 || (MAJOR_VERSIO /***/ }), -/* 640 */ +/* 639 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fs = __webpack_require__(641); +const fs = __webpack_require__(640); exports.fs = fs; /***/ }), -/* 641 */ +/* 640 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76017,15 +74715,15 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 642 */ +/* 641 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(628); -const constants_1 = __webpack_require__(639); -const utils = __webpack_require__(640); +const fsStat = __webpack_require__(627); +const constants_1 = __webpack_require__(638); +const utils = __webpack_require__(639); function read(dir, settings) { if (!settings.stats && constants_1.IS_SUPPORT_READDIR_WITH_FILE_TYPES) { return readdirWithFileTypes(dir, settings); @@ -76076,15 +74774,15 @@ exports.readdir = readdir; /***/ }), -/* 643 */ +/* 642 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsStat = __webpack_require__(628); -const fs = __webpack_require__(644); +const fsStat = __webpack_require__(627); +const fs = __webpack_require__(643); class Settings { constructor(_options = {}) { this._options = _options; @@ -76107,7 +74805,7 @@ exports.default = Settings; /***/ }), -/* 644 */ +/* 643 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76132,13 +74830,13 @@ exports.createFileSystemAdapter = createFileSystemAdapter; /***/ }), -/* 645 */ +/* 644 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var reusify = __webpack_require__(646) +var reusify = __webpack_require__(645) function fastqueue (context, worker, concurrency) { if (typeof context === 'function') { @@ -76312,7 +75010,7 @@ module.exports = fastqueue /***/ }), -/* 646 */ +/* 645 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76352,7 +75050,7 @@ module.exports = reusify /***/ }), -/* 647 */ +/* 646 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76383,13 +75081,13 @@ exports.joinPathSegments = joinPathSegments; /***/ }), -/* 648 */ +/* 647 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const common = __webpack_require__(647); +const common = __webpack_require__(646); class Reader { constructor(_root, _settings) { this._root = _root; @@ -76401,14 +75099,14 @@ exports.default = Reader; /***/ }), -/* 649 */ +/* 648 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const async_1 = __webpack_require__(635); +const async_1 = __webpack_require__(634); class StreamProvider { constructor(_root, _settings) { this._root = _root; @@ -76438,13 +75136,13 @@ exports.default = StreamProvider; /***/ }), -/* 650 */ +/* 649 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(651); +const sync_1 = __webpack_require__(650); class SyncProvider { constructor(_root, _settings) { this._root = _root; @@ -76459,15 +75157,15 @@ exports.default = SyncProvider; /***/ }), -/* 651 */ +/* 650 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsScandir = __webpack_require__(636); -const common = __webpack_require__(647); -const reader_1 = __webpack_require__(648); +const fsScandir = __webpack_require__(635); +const common = __webpack_require__(646); +const reader_1 = __webpack_require__(647); class SyncReader extends reader_1.default { constructor() { super(...arguments); @@ -76525,14 +75223,14 @@ exports.default = SyncReader; /***/ }), -/* 652 */ +/* 651 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsScandir = __webpack_require__(636); +const fsScandir = __webpack_require__(635); class Settings { constructor(_options = {}) { this._options = _options; @@ -76558,15 +75256,15 @@ exports.default = Settings; /***/ }), -/* 653 */ +/* 652 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const fsStat = __webpack_require__(628); -const utils = __webpack_require__(599); +const fsStat = __webpack_require__(627); +const utils = __webpack_require__(598); class Reader { constructor(_settings) { this._settings = _settings; @@ -76598,17 +75296,17 @@ exports.default = Reader; /***/ }), -/* 654 */ +/* 653 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(16); -const deep_1 = __webpack_require__(655); -const entry_1 = __webpack_require__(656); -const error_1 = __webpack_require__(657); -const entry_2 = __webpack_require__(658); +const deep_1 = __webpack_require__(654); +const entry_1 = __webpack_require__(655); +const error_1 = __webpack_require__(656); +const entry_2 = __webpack_require__(657); class Provider { constructor(_settings) { this._settings = _settings; @@ -76653,13 +75351,13 @@ exports.default = Provider; /***/ }), -/* 655 */ +/* 654 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(599); +const utils = __webpack_require__(598); class DeepFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -76719,13 +75417,13 @@ exports.default = DeepFilter; /***/ }), -/* 656 */ +/* 655 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(599); +const utils = __webpack_require__(598); class EntryFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -76780,13 +75478,13 @@ exports.default = EntryFilter; /***/ }), -/* 657 */ +/* 656 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(599); +const utils = __webpack_require__(598); class ErrorFilter { constructor(_settings) { this._settings = _settings; @@ -76802,13 +75500,13 @@ exports.default = ErrorFilter; /***/ }), -/* 658 */ +/* 657 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(599); +const utils = __webpack_require__(598); class EntryTransformer { constructor(_settings) { this._settings = _settings; @@ -76835,15 +75533,15 @@ exports.default = EntryTransformer; /***/ }), -/* 659 */ +/* 658 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(27); -const stream_2 = __webpack_require__(627); -const provider_1 = __webpack_require__(654); +const stream_2 = __webpack_require__(626); +const provider_1 = __webpack_require__(653); class ProviderStream extends provider_1.default { constructor() { super(...arguments); @@ -76871,14 +75569,14 @@ exports.default = ProviderStream; /***/ }), -/* 660 */ +/* 659 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(661); -const provider_1 = __webpack_require__(654); +const sync_1 = __webpack_require__(660); +const provider_1 = __webpack_require__(653); class ProviderSync extends provider_1.default { constructor() { super(...arguments); @@ -76901,15 +75599,15 @@ exports.default = ProviderSync; /***/ }), -/* 661 */ +/* 660 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsStat = __webpack_require__(628); -const fsWalk = __webpack_require__(633); -const reader_1 = __webpack_require__(653); +const fsStat = __webpack_require__(627); +const fsWalk = __webpack_require__(632); +const reader_1 = __webpack_require__(652); class ReaderSync extends reader_1.default { constructor() { super(...arguments); @@ -76951,7 +75649,7 @@ exports.default = ReaderSync; /***/ }), -/* 662 */ +/* 661 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77011,13 +75709,13 @@ exports.default = Settings; /***/ }), -/* 663 */ +/* 662 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(664); +const pathType = __webpack_require__(663); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -77093,7 +75791,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 664 */ +/* 663 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77143,7 +75841,7 @@ exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 665 */ +/* 664 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77151,9 +75849,9 @@ exports.isSymlinkSync = isTypeSync.bind(null, 'lstatSync', 'isSymbolicLink'); const {promisify} = __webpack_require__(29); const fs = __webpack_require__(23); const path = __webpack_require__(16); -const fastGlob = __webpack_require__(597); -const gitIgnore = __webpack_require__(666); -const slash = __webpack_require__(667); +const fastGlob = __webpack_require__(596); +const gitIgnore = __webpack_require__(665); +const slash = __webpack_require__(666); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -77267,7 +75965,7 @@ module.exports.sync = options => { /***/ }), -/* 666 */ +/* 665 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -77858,7 +76556,7 @@ if ( /***/ }), -/* 667 */ +/* 666 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77876,7 +76574,7 @@ module.exports = path => { /***/ }), -/* 668 */ +/* 667 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77929,7 +76627,7 @@ module.exports = { /***/ }), -/* 669 */ +/* 668 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77951,7 +76649,7 @@ module.exports = path_ => { /***/ }), -/* 670 */ +/* 669 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77979,7 +76677,7 @@ module.exports = (childPath, parentPath) => { /***/ }), -/* 671 */ +/* 670 */ /***/ (function(module, exports, __webpack_require__) { const assert = __webpack_require__(30) @@ -77987,7 +76685,7 @@ const path = __webpack_require__(16) const fs = __webpack_require__(23) let glob = undefined try { - glob = __webpack_require__(592) + glob = __webpack_require__(591) } catch (_err) { // treat glob as optional. } @@ -78353,12 +77051,12 @@ rimraf.sync = rimrafSync /***/ }), -/* 672 */ +/* 671 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const AggregateError = __webpack_require__(673); +const AggregateError = __webpack_require__(672); module.exports = async ( iterable, @@ -78441,13 +77139,13 @@ module.exports = async ( /***/ }), -/* 673 */ +/* 672 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const indentString = __webpack_require__(674); -const cleanStack = __webpack_require__(675); +const indentString = __webpack_require__(673); +const cleanStack = __webpack_require__(674); const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, ''); @@ -78495,7 +77193,7 @@ module.exports = AggregateError; /***/ }), -/* 674 */ +/* 673 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78537,7 +77235,7 @@ module.exports = (string, count = 1, options) => { /***/ }), -/* 675 */ +/* 674 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78584,15 +77282,15 @@ module.exports = (stack, options) => { /***/ }), -/* 676 */ +/* 675 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(677); -const cliCursor = __webpack_require__(681); -const cliSpinners = __webpack_require__(685); -const logSymbols = __webpack_require__(566); +const chalk = __webpack_require__(676); +const cliCursor = __webpack_require__(680); +const cliSpinners = __webpack_require__(684); +const logSymbols = __webpack_require__(565); class Ora { constructor(options) { @@ -78739,16 +77437,16 @@ module.exports.promise = (action, options) => { /***/ }), -/* 677 */ +/* 676 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(3); -const ansiStyles = __webpack_require__(678); -const stdoutColor = __webpack_require__(679).stdout; +const ansiStyles = __webpack_require__(677); +const stdoutColor = __webpack_require__(678).stdout; -const template = __webpack_require__(680); +const template = __webpack_require__(679); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -78974,7 +77672,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 678 */ +/* 677 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79147,7 +77845,7 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)(module))) /***/ }), -/* 679 */ +/* 678 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79289,7 +77987,7 @@ module.exports = { /***/ }), -/* 680 */ +/* 679 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79424,12 +78122,12 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 681 */ +/* 680 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(682); +const restoreCursor = __webpack_require__(681); let hidden = false; @@ -79470,12 +78168,12 @@ exports.toggle = (force, stream) => { /***/ }), -/* 682 */ +/* 681 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const onetime = __webpack_require__(683); +const onetime = __webpack_require__(682); const signalExit = __webpack_require__(377); module.exports = onetime(() => { @@ -79486,12 +78184,12 @@ module.exports = onetime(() => { /***/ }), -/* 683 */ +/* 682 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const mimicFn = __webpack_require__(684); +const mimicFn = __webpack_require__(683); module.exports = (fn, opts) => { // TODO: Remove this in v3 @@ -79532,7 +78230,7 @@ module.exports = (fn, opts) => { /***/ }), -/* 684 */ +/* 683 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79548,22 +78246,22 @@ module.exports = (to, from) => { /***/ }), -/* 685 */ +/* 684 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(686); +module.exports = __webpack_require__(685); /***/ }), -/* 686 */ +/* 685 */ /***/ (function(module) { module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]}}"); /***/ }), -/* 687 */ +/* 686 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -79623,7 +78321,7 @@ const RunCommand = { }; /***/ }), -/* 688 */ +/* 687 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -79634,7 +78332,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(34); /* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(500); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(501); -/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(689); +/* harmony import */ var _utils_watch__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(688); /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -79718,7 +78416,7 @@ const WatchCommand = { }; /***/ }), -/* 689 */ +/* 688 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -79792,7 +78490,7 @@ function waitUntilWatchIsReady(stream, opts = {}) { } /***/ }), -/* 690 */ +/* 689 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -79800,15 +78498,15 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "runCommand", function() { return runCommand; }); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(691); +/* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(690); /* harmony import */ var indent_string__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(indent_string__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(692); +/* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(691); /* harmony import */ var wrap_ansi__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(wrap_ansi__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(515); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(34); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(501); -/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(699); -/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(700); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(698); +/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(699); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -79896,7 +78594,7 @@ function toArray(value) { } /***/ }), -/* 691 */ +/* 690 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79930,13 +78628,13 @@ module.exports = (str, count, opts) => { /***/ }), -/* 692 */ +/* 691 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stringWidth = __webpack_require__(693); -const stripAnsi = __webpack_require__(697); +const stringWidth = __webpack_require__(692); +const stripAnsi = __webpack_require__(696); const ESCAPES = new Set([ '\u001B', @@ -80130,13 +78828,13 @@ module.exports = (str, cols, opts) => { /***/ }), -/* 693 */ +/* 692 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const stripAnsi = __webpack_require__(694); -const isFullwidthCodePoint = __webpack_require__(696); +const stripAnsi = __webpack_require__(693); +const isFullwidthCodePoint = __webpack_require__(695); module.exports = str => { if (typeof str !== 'string' || str.length === 0) { @@ -80173,18 +78871,18 @@ module.exports = str => { /***/ }), -/* 694 */ +/* 693 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(695); +const ansiRegex = __webpack_require__(694); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 695 */ +/* 694 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80201,7 +78899,7 @@ module.exports = () => { /***/ }), -/* 696 */ +/* 695 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80254,18 +78952,18 @@ module.exports = x => { /***/ }), -/* 697 */ +/* 696 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(698); +const ansiRegex = __webpack_require__(697); module.exports = input => typeof input === 'string' ? input.replace(ansiRegex(), '') : input; /***/ }), -/* 698 */ +/* 697 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80282,7 +78980,7 @@ module.exports = () => { /***/ }), -/* 699 */ +/* 698 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -80435,7 +79133,7 @@ function addProjectToTree(tree, pathParts, project) { } /***/ }), -/* 700 */ +/* 699 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -80443,10 +79141,10 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Kibana", function() { return Kibana; }); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(701); +/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(700); /* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(multimatch__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(501); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(580); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(579); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -80578,15 +79276,15 @@ class Kibana { } /***/ }), -/* 701 */ +/* 700 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const minimatch = __webpack_require__(505); -const arrayUnion = __webpack_require__(702); -const arrayDiffer = __webpack_require__(703); -const arrify = __webpack_require__(704); +const arrayUnion = __webpack_require__(701); +const arrayDiffer = __webpack_require__(702); +const arrify = __webpack_require__(703); module.exports = (list, patterns, options = {}) => { list = arrify(list); @@ -80610,7 +79308,7 @@ module.exports = (list, patterns, options = {}) => { /***/ }), -/* 702 */ +/* 701 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80622,7 +79320,7 @@ module.exports = (...arguments_) => { /***/ }), -/* 703 */ +/* 702 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80637,7 +79335,7 @@ module.exports = arrayDiffer; /***/ }), -/* 704 */ +/* 703 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80667,15 +79365,15 @@ module.exports = arrify; /***/ }), -/* 705 */ +/* 704 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(706); +/* harmony import */ var _build_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(705); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return _build_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildProductionProjects"]; }); -/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(929); +/* harmony import */ var _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(928); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "prepareExternalProjectDependencies", function() { return _prepare_project_dependencies__WEBPACK_IMPORTED_MODULE_1__["prepareExternalProjectDependencies"]; }); /* @@ -80700,19 +79398,19 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 706 */ +/* 705 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProductionProjects", function() { return buildProductionProjects; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(707); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(706); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(588); +/* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(587); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(580); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(579); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(34); /* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(517); @@ -80848,7 +79546,7 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { } /***/ }), -/* 707 */ +/* 706 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80856,13 +79554,13 @@ async function copyToBuild(project, kibanaRoot, buildRoot) { const EventEmitter = __webpack_require__(379); const path = __webpack_require__(16); const os = __webpack_require__(11); -const pAll = __webpack_require__(708); -const arrify = __webpack_require__(710); -const globby = __webpack_require__(711); -const isGlob = __webpack_require__(606); -const cpFile = __webpack_require__(914); -const junk = __webpack_require__(926); -const CpyError = __webpack_require__(927); +const pAll = __webpack_require__(707); +const arrify = __webpack_require__(709); +const globby = __webpack_require__(710); +const isGlob = __webpack_require__(605); +const cpFile = __webpack_require__(913); +const junk = __webpack_require__(925); +const CpyError = __webpack_require__(926); const defaultOptions = { ignoreJunk: true @@ -80981,12 +79679,12 @@ module.exports = (source, destination, { /***/ }), -/* 708 */ +/* 707 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pMap = __webpack_require__(709); +const pMap = __webpack_require__(708); module.exports = (iterable, options) => pMap(iterable, element => element(), options); // TODO: Remove this for the next major release @@ -80994,7 +79692,7 @@ module.exports.default = module.exports; /***/ }), -/* 709 */ +/* 708 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81073,7 +79771,7 @@ module.exports.default = pMap; /***/ }), -/* 710 */ +/* 709 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81103,17 +79801,17 @@ module.exports = arrify; /***/ }), -/* 711 */ +/* 710 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const arrayUnion = __webpack_require__(712); -const glob = __webpack_require__(714); -const fastGlob = __webpack_require__(719); -const dirGlob = __webpack_require__(907); -const gitignore = __webpack_require__(910); +const arrayUnion = __webpack_require__(711); +const glob = __webpack_require__(713); +const fastGlob = __webpack_require__(718); +const dirGlob = __webpack_require__(906); +const gitignore = __webpack_require__(909); const DEFAULT_FILTER = () => false; @@ -81258,12 +79956,12 @@ module.exports.gitignore = gitignore; /***/ }), -/* 712 */ +/* 711 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var arrayUniq = __webpack_require__(713); +var arrayUniq = __webpack_require__(712); module.exports = function () { return arrayUniq([].concat.apply([], arguments)); @@ -81271,7 +79969,7 @@ module.exports = function () { /***/ }), -/* 713 */ +/* 712 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81340,7 +80038,7 @@ if ('Set' in global) { /***/ }), -/* 714 */ +/* 713 */ /***/ (function(module, exports, __webpack_require__) { // Approach: @@ -81389,13 +80087,13 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(503) var minimatch = __webpack_require__(505) var Minimatch = minimatch.Minimatch -var inherits = __webpack_require__(715) +var inherits = __webpack_require__(714) var EE = __webpack_require__(379).EventEmitter var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(511) -var globSync = __webpack_require__(717) -var common = __webpack_require__(718) +var globSync = __webpack_require__(716) +var common = __webpack_require__(717) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -82136,7 +80834,7 @@ Glob.prototype._stat2 = function (f, abs, er, stat, cb) { /***/ }), -/* 715 */ +/* 714 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -82146,12 +80844,12 @@ try { module.exports = util.inherits; } catch (e) { /* istanbul ignore next */ - module.exports = __webpack_require__(716); + module.exports = __webpack_require__(715); } /***/ }), -/* 716 */ +/* 715 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -82184,7 +80882,7 @@ if (typeof Object.create === 'function') { /***/ }), -/* 717 */ +/* 716 */ /***/ (function(module, exports, __webpack_require__) { module.exports = globSync @@ -82194,12 +80892,12 @@ var fs = __webpack_require__(23) var rp = __webpack_require__(503) var minimatch = __webpack_require__(505) var Minimatch = minimatch.Minimatch -var Glob = __webpack_require__(714).Glob +var Glob = __webpack_require__(713).Glob var util = __webpack_require__(29) var path = __webpack_require__(16) var assert = __webpack_require__(30) var isAbsolute = __webpack_require__(511) -var common = __webpack_require__(718) +var common = __webpack_require__(717) var alphasort = common.alphasort var alphasorti = common.alphasorti var setopts = common.setopts @@ -82676,7 +81374,7 @@ GlobSync.prototype._makeAbs = function (f) { /***/ }), -/* 718 */ +/* 717 */ /***/ (function(module, exports, __webpack_require__) { exports.alphasort = alphasort @@ -82922,10 +81620,10 @@ function childrenIgnored (self, path) { /***/ }), -/* 719 */ +/* 718 */ /***/ (function(module, exports, __webpack_require__) { -const pkg = __webpack_require__(720); +const pkg = __webpack_require__(719); module.exports = pkg.async; module.exports.default = pkg.async; @@ -82938,19 +81636,19 @@ module.exports.generateTasks = pkg.generateTasks; /***/ }), -/* 720 */ +/* 719 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var optionsManager = __webpack_require__(721); -var taskManager = __webpack_require__(722); -var reader_async_1 = __webpack_require__(878); -var reader_stream_1 = __webpack_require__(902); -var reader_sync_1 = __webpack_require__(903); -var arrayUtils = __webpack_require__(905); -var streamUtils = __webpack_require__(906); +var optionsManager = __webpack_require__(720); +var taskManager = __webpack_require__(721); +var reader_async_1 = __webpack_require__(877); +var reader_stream_1 = __webpack_require__(901); +var reader_sync_1 = __webpack_require__(902); +var arrayUtils = __webpack_require__(904); +var streamUtils = __webpack_require__(905); /** * Synchronous API. */ @@ -83016,7 +81714,7 @@ function isString(source) { /***/ }), -/* 721 */ +/* 720 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83054,13 +81752,13 @@ exports.prepare = prepare; /***/ }), -/* 722 */ +/* 721 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(723); +var patternUtils = __webpack_require__(722); /** * Generate tasks based on parent directory of each pattern. */ @@ -83151,16 +81849,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 723 */ +/* 722 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var globParent = __webpack_require__(724); -var isGlob = __webpack_require__(727); -var micromatch = __webpack_require__(728); +var globParent = __webpack_require__(723); +var isGlob = __webpack_require__(726); +var micromatch = __webpack_require__(727); var GLOBSTAR = '**'; /** * Return true for static pattern. @@ -83306,15 +82004,15 @@ exports.matchAny = matchAny; /***/ }), -/* 724 */ +/* 723 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(16); -var isglob = __webpack_require__(725); -var pathDirname = __webpack_require__(726); +var isglob = __webpack_require__(724); +var pathDirname = __webpack_require__(725); var isWin32 = __webpack_require__(11).platform() === 'win32'; module.exports = function globParent(str) { @@ -83337,7 +82035,7 @@ module.exports = function globParent(str) { /***/ }), -/* 725 */ +/* 724 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -83347,7 +82045,7 @@ module.exports = function globParent(str) { * Licensed under the MIT License. */ -var isExtglob = __webpack_require__(607); +var isExtglob = __webpack_require__(606); module.exports = function isGlob(str) { if (typeof str !== 'string' || str === '') { @@ -83368,7 +82066,7 @@ module.exports = function isGlob(str) { /***/ }), -/* 726 */ +/* 725 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83518,7 +82216,7 @@ module.exports.win32 = win32; /***/ }), -/* 727 */ +/* 726 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -83528,7 +82226,7 @@ module.exports.win32 = win32; * Released under the MIT License. */ -var isExtglob = __webpack_require__(607); +var isExtglob = __webpack_require__(606); var chars = { '{': '}', '(': ')', '[': ']'}; module.exports = function isGlob(str, options) { @@ -83570,7 +82268,7 @@ module.exports = function isGlob(str, options) { /***/ }), -/* 728 */ +/* 727 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83581,18 +82279,18 @@ module.exports = function isGlob(str, options) { */ var util = __webpack_require__(29); -var braces = __webpack_require__(729); -var toRegex = __webpack_require__(831); -var extend = __webpack_require__(839); +var braces = __webpack_require__(728); +var toRegex = __webpack_require__(830); +var extend = __webpack_require__(838); /** * Local dependencies */ -var compilers = __webpack_require__(842); -var parsers = __webpack_require__(874); -var cache = __webpack_require__(875); -var utils = __webpack_require__(876); +var compilers = __webpack_require__(841); +var parsers = __webpack_require__(873); +var cache = __webpack_require__(874); +var utils = __webpack_require__(875); var MAX_LENGTH = 1024 * 64; /** @@ -84454,7 +83152,7 @@ module.exports = micromatch; /***/ }), -/* 729 */ +/* 728 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84464,18 +83162,18 @@ module.exports = micromatch; * Module dependencies */ -var toRegex = __webpack_require__(730); -var unique = __webpack_require__(742); -var extend = __webpack_require__(739); +var toRegex = __webpack_require__(729); +var unique = __webpack_require__(741); +var extend = __webpack_require__(738); /** * Local dependencies */ -var compilers = __webpack_require__(743); -var parsers = __webpack_require__(758); -var Braces = __webpack_require__(768); -var utils = __webpack_require__(744); +var compilers = __webpack_require__(742); +var parsers = __webpack_require__(757); +var Braces = __webpack_require__(767); +var utils = __webpack_require__(743); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -84779,15 +83477,15 @@ module.exports = braces; /***/ }), -/* 730 */ +/* 729 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(731); -var extend = __webpack_require__(739); -var not = __webpack_require__(741); +var define = __webpack_require__(730); +var extend = __webpack_require__(738); +var not = __webpack_require__(740); var MAX_LENGTH = 1024 * 64; /** @@ -84934,7 +83632,7 @@ module.exports.makeRe = makeRe; /***/ }), -/* 731 */ +/* 730 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84947,7 +83645,7 @@ module.exports.makeRe = makeRe; -var isDescriptor = __webpack_require__(732); +var isDescriptor = __webpack_require__(731); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -84972,7 +83670,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 732 */ +/* 731 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84985,9 +83683,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(733); -var isAccessor = __webpack_require__(734); -var isData = __webpack_require__(737); +var typeOf = __webpack_require__(732); +var isAccessor = __webpack_require__(733); +var isData = __webpack_require__(736); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -85001,7 +83699,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 733 */ +/* 732 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -85154,7 +83852,7 @@ function isBuffer(val) { /***/ }), -/* 734 */ +/* 733 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85167,7 +83865,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(735); +var typeOf = __webpack_require__(734); // accessor descriptor properties var accessor = { @@ -85230,10 +83928,10 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 735 */ +/* 734 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(736); +var isBuffer = __webpack_require__(735); var toString = Object.prototype.toString; /** @@ -85352,7 +84050,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 736 */ +/* 735 */ /***/ (function(module, exports) { /*! @@ -85379,7 +84077,7 @@ function isSlowBuffer (obj) { /***/ }), -/* 737 */ +/* 736 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85392,7 +84090,7 @@ function isSlowBuffer (obj) { -var typeOf = __webpack_require__(738); +var typeOf = __webpack_require__(737); // data descriptor properties var data = { @@ -85441,10 +84139,10 @@ module.exports = isDataDescriptor; /***/ }), -/* 738 */ +/* 737 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(736); +var isBuffer = __webpack_require__(735); var toString = Object.prototype.toString; /** @@ -85563,13 +84261,13 @@ module.exports = function kindOf(val) { /***/ }), -/* 739 */ +/* 738 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(740); +var isObject = __webpack_require__(739); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -85603,7 +84301,7 @@ function hasOwn(obj, key) { /***/ }), -/* 740 */ +/* 739 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85623,13 +84321,13 @@ module.exports = function isExtendable(val) { /***/ }), -/* 741 */ +/* 740 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(739); +var extend = __webpack_require__(738); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -85696,7 +84394,7 @@ module.exports = toRegex; /***/ }), -/* 742 */ +/* 741 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85746,13 +84444,13 @@ module.exports.immutable = function uniqueImmutable(arr) { /***/ }), -/* 743 */ +/* 742 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(744); +var utils = __webpack_require__(743); module.exports = function(braces, options) { braces.compiler @@ -86035,25 +84733,25 @@ function hasQueue(node) { /***/ }), -/* 744 */ +/* 743 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var splitString = __webpack_require__(745); +var splitString = __webpack_require__(744); var utils = module.exports; /** * Module dependencies */ -utils.extend = __webpack_require__(739); -utils.flatten = __webpack_require__(751); -utils.isObject = __webpack_require__(749); -utils.fillRange = __webpack_require__(752); -utils.repeat = __webpack_require__(757); -utils.unique = __webpack_require__(742); +utils.extend = __webpack_require__(738); +utils.flatten = __webpack_require__(750); +utils.isObject = __webpack_require__(748); +utils.fillRange = __webpack_require__(751); +utils.repeat = __webpack_require__(756); +utils.unique = __webpack_require__(741); utils.define = function(obj, key, val) { Object.defineProperty(obj, key, { @@ -86385,7 +85083,7 @@ utils.escapeRegex = function(str) { /***/ }), -/* 745 */ +/* 744 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86398,7 +85096,7 @@ utils.escapeRegex = function(str) { -var extend = __webpack_require__(746); +var extend = __webpack_require__(745); module.exports = function(str, options, fn) { if (typeof str !== 'string') { @@ -86563,14 +85261,14 @@ function keepEscaping(opts, str, idx) { /***/ }), -/* 746 */ +/* 745 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(747); -var assignSymbols = __webpack_require__(750); +var isExtendable = __webpack_require__(746); +var assignSymbols = __webpack_require__(749); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -86630,7 +85328,7 @@ function isEnum(obj, key) { /***/ }), -/* 747 */ +/* 746 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86643,7 +85341,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(748); +var isPlainObject = __webpack_require__(747); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -86651,7 +85349,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 748 */ +/* 747 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86664,7 +85362,7 @@ module.exports = function isExtendable(val) { -var isObject = __webpack_require__(749); +var isObject = __webpack_require__(748); function isObjectObject(o) { return isObject(o) === true @@ -86695,7 +85393,7 @@ module.exports = function isPlainObject(o) { /***/ }), -/* 749 */ +/* 748 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86714,7 +85412,7 @@ module.exports = function isObject(val) { /***/ }), -/* 750 */ +/* 749 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86761,7 +85459,7 @@ module.exports = function(receiver, objects) { /***/ }), -/* 751 */ +/* 750 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86790,7 +85488,7 @@ function flat(arr, res) { /***/ }), -/* 752 */ +/* 751 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86804,10 +85502,10 @@ function flat(arr, res) { var util = __webpack_require__(29); -var isNumber = __webpack_require__(753); -var extend = __webpack_require__(739); -var repeat = __webpack_require__(755); -var toRegex = __webpack_require__(756); +var isNumber = __webpack_require__(752); +var extend = __webpack_require__(738); +var repeat = __webpack_require__(754); +var toRegex = __webpack_require__(755); /** * Return a range of numbers or letters. @@ -87005,7 +85703,7 @@ module.exports = fillRange; /***/ }), -/* 753 */ +/* 752 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87018,7 +85716,7 @@ module.exports = fillRange; -var typeOf = __webpack_require__(754); +var typeOf = __webpack_require__(753); module.exports = function isNumber(num) { var type = typeOf(num); @@ -87034,10 +85732,10 @@ module.exports = function isNumber(num) { /***/ }), -/* 754 */ +/* 753 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(736); +var isBuffer = __webpack_require__(735); var toString = Object.prototype.toString; /** @@ -87156,7 +85854,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 755 */ +/* 754 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87233,7 +85931,7 @@ function repeat(str, num) { /***/ }), -/* 756 */ +/* 755 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87246,8 +85944,8 @@ function repeat(str, num) { -var repeat = __webpack_require__(755); -var isNumber = __webpack_require__(753); +var repeat = __webpack_require__(754); +var isNumber = __webpack_require__(752); var cache = {}; function toRegexRange(min, max, options) { @@ -87534,7 +86232,7 @@ module.exports = toRegexRange; /***/ }), -/* 757 */ +/* 756 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87559,14 +86257,14 @@ module.exports = function repeat(ele, num) { /***/ }), -/* 758 */ +/* 757 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Node = __webpack_require__(759); -var utils = __webpack_require__(744); +var Node = __webpack_require__(758); +var utils = __webpack_require__(743); /** * Braces parsers @@ -87926,15 +86624,15 @@ function concatNodes(pos, node, parent, options) { /***/ }), -/* 759 */ +/* 758 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(749); -var define = __webpack_require__(760); -var utils = __webpack_require__(767); +var isObject = __webpack_require__(748); +var define = __webpack_require__(759); +var utils = __webpack_require__(766); var ownNames; /** @@ -88425,7 +87123,7 @@ exports = module.exports = Node; /***/ }), -/* 760 */ +/* 759 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88438,7 +87136,7 @@ exports = module.exports = Node; -var isDescriptor = __webpack_require__(761); +var isDescriptor = __webpack_require__(760); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -88463,7 +87161,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 761 */ +/* 760 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88476,9 +87174,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(762); -var isAccessor = __webpack_require__(763); -var isData = __webpack_require__(765); +var typeOf = __webpack_require__(761); +var isAccessor = __webpack_require__(762); +var isData = __webpack_require__(764); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -88492,7 +87190,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 762 */ +/* 761 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -88627,7 +87325,7 @@ function isBuffer(val) { /***/ }), -/* 763 */ +/* 762 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88640,7 +87338,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(764); +var typeOf = __webpack_require__(763); // accessor descriptor properties var accessor = { @@ -88703,7 +87401,7 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 764 */ +/* 763 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -88838,7 +87536,7 @@ function isBuffer(val) { /***/ }), -/* 765 */ +/* 764 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88851,7 +87549,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(766); +var typeOf = __webpack_require__(765); module.exports = function isDataDescriptor(obj, prop) { // data descriptor properties @@ -88894,7 +87592,7 @@ module.exports = function isDataDescriptor(obj, prop) { /***/ }), -/* 766 */ +/* 765 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -89029,13 +87727,13 @@ function isBuffer(val) { /***/ }), -/* 767 */ +/* 766 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(754); +var typeOf = __webpack_require__(753); var utils = module.exports; /** @@ -90055,17 +88753,17 @@ function assert(val, message) { /***/ }), -/* 768 */ +/* 767 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(739); -var Snapdragon = __webpack_require__(769); -var compilers = __webpack_require__(743); -var parsers = __webpack_require__(758); -var utils = __webpack_require__(744); +var extend = __webpack_require__(738); +var Snapdragon = __webpack_require__(768); +var compilers = __webpack_require__(742); +var parsers = __webpack_require__(757); +var utils = __webpack_require__(743); /** * Customize Snapdragon parser and renderer @@ -90166,17 +88864,17 @@ module.exports = Braces; /***/ }), -/* 769 */ +/* 768 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Base = __webpack_require__(770); -var define = __webpack_require__(731); -var Compiler = __webpack_require__(799); -var Parser = __webpack_require__(828); -var utils = __webpack_require__(808); +var Base = __webpack_require__(769); +var define = __webpack_require__(730); +var Compiler = __webpack_require__(798); +var Parser = __webpack_require__(827); +var utils = __webpack_require__(807); var regexCache = {}; var cache = {}; @@ -90347,20 +89045,20 @@ module.exports.Parser = Parser; /***/ }), -/* 770 */ +/* 769 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var define = __webpack_require__(771); -var CacheBase = __webpack_require__(772); -var Emitter = __webpack_require__(773); -var isObject = __webpack_require__(749); -var merge = __webpack_require__(790); -var pascal = __webpack_require__(793); -var cu = __webpack_require__(794); +var define = __webpack_require__(770); +var CacheBase = __webpack_require__(771); +var Emitter = __webpack_require__(772); +var isObject = __webpack_require__(748); +var merge = __webpack_require__(789); +var pascal = __webpack_require__(792); +var cu = __webpack_require__(793); /** * Optionally define a custom `cache` namespace to use. @@ -90789,7 +89487,7 @@ module.exports.namespace = namespace; /***/ }), -/* 771 */ +/* 770 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90802,7 +89500,7 @@ module.exports.namespace = namespace; -var isDescriptor = __webpack_require__(761); +var isDescriptor = __webpack_require__(760); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -90827,21 +89525,21 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 772 */ +/* 771 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(749); -var Emitter = __webpack_require__(773); -var visit = __webpack_require__(774); -var toPath = __webpack_require__(777); -var union = __webpack_require__(778); -var del = __webpack_require__(782); -var get = __webpack_require__(780); -var has = __webpack_require__(787); -var set = __webpack_require__(781); +var isObject = __webpack_require__(748); +var Emitter = __webpack_require__(772); +var visit = __webpack_require__(773); +var toPath = __webpack_require__(776); +var union = __webpack_require__(777); +var del = __webpack_require__(781); +var get = __webpack_require__(779); +var has = __webpack_require__(786); +var set = __webpack_require__(780); /** * Create a `Cache` constructor that when instantiated will @@ -91095,7 +89793,7 @@ module.exports.namespace = namespace; /***/ }), -/* 773 */ +/* 772 */ /***/ (function(module, exports, __webpack_require__) { @@ -91264,7 +89962,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 774 */ +/* 773 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91277,8 +89975,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(775); -var mapVisit = __webpack_require__(776); +var visit = __webpack_require__(774); +var mapVisit = __webpack_require__(775); module.exports = function(collection, method, val) { var result; @@ -91301,7 +89999,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 775 */ +/* 774 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91314,7 +90012,7 @@ module.exports = function(collection, method, val) { -var isObject = __webpack_require__(749); +var isObject = __webpack_require__(748); module.exports = function visit(thisArg, method, target, val) { if (!isObject(thisArg) && typeof thisArg !== 'function') { @@ -91341,14 +90039,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 776 */ +/* 775 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var visit = __webpack_require__(775); +var visit = __webpack_require__(774); /** * Map `visit` over an array of objects. @@ -91385,7 +90083,7 @@ function isObject(val) { /***/ }), -/* 777 */ +/* 776 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91398,7 +90096,7 @@ function isObject(val) { -var typeOf = __webpack_require__(754); +var typeOf = __webpack_require__(753); module.exports = function toPath(args) { if (typeOf(args) !== 'arguments') { @@ -91425,16 +90123,16 @@ function filter(arr) { /***/ }), -/* 778 */ +/* 777 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(740); -var union = __webpack_require__(779); -var get = __webpack_require__(780); -var set = __webpack_require__(781); +var isObject = __webpack_require__(739); +var union = __webpack_require__(778); +var get = __webpack_require__(779); +var set = __webpack_require__(780); module.exports = function unionValue(obj, prop, value) { if (!isObject(obj)) { @@ -91462,7 +90160,7 @@ function arrayify(val) { /***/ }), -/* 779 */ +/* 778 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91498,7 +90196,7 @@ module.exports = function union(init) { /***/ }), -/* 780 */ +/* 779 */ /***/ (function(module, exports) { /*! @@ -91554,7 +90252,7 @@ function toString(val) { /***/ }), -/* 781 */ +/* 780 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91567,10 +90265,10 @@ function toString(val) { -var split = __webpack_require__(745); -var extend = __webpack_require__(739); -var isPlainObject = __webpack_require__(748); -var isObject = __webpack_require__(740); +var split = __webpack_require__(744); +var extend = __webpack_require__(738); +var isPlainObject = __webpack_require__(747); +var isObject = __webpack_require__(739); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -91616,7 +90314,7 @@ function isValidKey(key) { /***/ }), -/* 782 */ +/* 781 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91629,8 +90327,8 @@ function isValidKey(key) { -var isObject = __webpack_require__(749); -var has = __webpack_require__(783); +var isObject = __webpack_require__(748); +var has = __webpack_require__(782); module.exports = function unset(obj, prop) { if (!isObject(obj)) { @@ -91655,7 +90353,7 @@ module.exports = function unset(obj, prop) { /***/ }), -/* 783 */ +/* 782 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91668,9 +90366,9 @@ module.exports = function unset(obj, prop) { -var isObject = __webpack_require__(784); -var hasValues = __webpack_require__(786); -var get = __webpack_require__(780); +var isObject = __webpack_require__(783); +var hasValues = __webpack_require__(785); +var get = __webpack_require__(779); module.exports = function(obj, prop, noZero) { if (isObject(obj)) { @@ -91681,7 +90379,7 @@ module.exports = function(obj, prop, noZero) { /***/ }), -/* 784 */ +/* 783 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91694,7 +90392,7 @@ module.exports = function(obj, prop, noZero) { -var isArray = __webpack_require__(785); +var isArray = __webpack_require__(784); module.exports = function isObject(val) { return val != null && typeof val === 'object' && isArray(val) === false; @@ -91702,7 +90400,7 @@ module.exports = function isObject(val) { /***/ }), -/* 785 */ +/* 784 */ /***/ (function(module, exports) { var toString = {}.toString; @@ -91713,7 +90411,7 @@ module.exports = Array.isArray || function (arr) { /***/ }), -/* 786 */ +/* 785 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91756,7 +90454,7 @@ module.exports = function hasValue(o, noZero) { /***/ }), -/* 787 */ +/* 786 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91769,9 +90467,9 @@ module.exports = function hasValue(o, noZero) { -var isObject = __webpack_require__(749); -var hasValues = __webpack_require__(788); -var get = __webpack_require__(780); +var isObject = __webpack_require__(748); +var hasValues = __webpack_require__(787); +var get = __webpack_require__(779); module.exports = function(val, prop) { return hasValues(isObject(val) && prop ? get(val, prop) : val); @@ -91779,7 +90477,7 @@ module.exports = function(val, prop) { /***/ }), -/* 788 */ +/* 787 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91792,8 +90490,8 @@ module.exports = function(val, prop) { -var typeOf = __webpack_require__(789); -var isNumber = __webpack_require__(753); +var typeOf = __webpack_require__(788); +var isNumber = __webpack_require__(752); module.exports = function hasValue(val) { // is-number checks for NaN and other edge cases @@ -91846,10 +90544,10 @@ module.exports = function hasValue(val) { /***/ }), -/* 789 */ +/* 788 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(736); +var isBuffer = __webpack_require__(735); var toString = Object.prototype.toString; /** @@ -91971,14 +90669,14 @@ module.exports = function kindOf(val) { /***/ }), -/* 790 */ +/* 789 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(791); -var forIn = __webpack_require__(792); +var isExtendable = __webpack_require__(790); +var forIn = __webpack_require__(791); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -92042,7 +90740,7 @@ module.exports = mixinDeep; /***/ }), -/* 791 */ +/* 790 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92055,7 +90753,7 @@ module.exports = mixinDeep; -var isPlainObject = __webpack_require__(748); +var isPlainObject = __webpack_require__(747); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -92063,7 +90761,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 792 */ +/* 791 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92086,7 +90784,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 793 */ +/* 792 */ /***/ (function(module, exports) { /*! @@ -92113,14 +90811,14 @@ module.exports = pascalcase; /***/ }), -/* 794 */ +/* 793 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(29); -var utils = __webpack_require__(795); +var utils = __webpack_require__(794); /** * Expose class utils @@ -92485,7 +91183,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 795 */ +/* 794 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92499,10 +91197,10 @@ var utils = {}; * Lazily required module dependencies */ -utils.union = __webpack_require__(779); -utils.define = __webpack_require__(731); -utils.isObj = __webpack_require__(749); -utils.staticExtend = __webpack_require__(796); +utils.union = __webpack_require__(778); +utils.define = __webpack_require__(730); +utils.isObj = __webpack_require__(748); +utils.staticExtend = __webpack_require__(795); /** @@ -92513,7 +91211,7 @@ module.exports = utils; /***/ }), -/* 796 */ +/* 795 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92526,8 +91224,8 @@ module.exports = utils; -var copy = __webpack_require__(797); -var define = __webpack_require__(731); +var copy = __webpack_require__(796); +var define = __webpack_require__(730); var util = __webpack_require__(29); /** @@ -92610,15 +91308,15 @@ module.exports = extend; /***/ }), -/* 797 */ +/* 796 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(754); -var copyDescriptor = __webpack_require__(798); -var define = __webpack_require__(731); +var typeOf = __webpack_require__(753); +var copyDescriptor = __webpack_require__(797); +var define = __webpack_require__(730); /** * Copy static properties, prototype properties, and descriptors from one object to another. @@ -92791,7 +91489,7 @@ module.exports.has = has; /***/ }), -/* 798 */ +/* 797 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92879,16 +91577,16 @@ function isObject(val) { /***/ }), -/* 799 */ +/* 798 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(800); -var define = __webpack_require__(731); -var debug = __webpack_require__(802)('snapdragon:compiler'); -var utils = __webpack_require__(808); +var use = __webpack_require__(799); +var define = __webpack_require__(730); +var debug = __webpack_require__(801)('snapdragon:compiler'); +var utils = __webpack_require__(807); /** * Create a new `Compiler` with the given `options`. @@ -93042,7 +91740,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(827); + var sourcemaps = __webpack_require__(826); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -93063,7 +91761,7 @@ module.exports = Compiler; /***/ }), -/* 800 */ +/* 799 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -93076,7 +91774,7 @@ module.exports = Compiler; -var utils = __webpack_require__(801); +var utils = __webpack_require__(800); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -93191,7 +91889,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 801 */ +/* 800 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -93205,8 +91903,8 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(731); -utils.isObject = __webpack_require__(749); +utils.define = __webpack_require__(730); +utils.isObject = __webpack_require__(748); utils.isString = function(val) { @@ -93221,7 +91919,7 @@ module.exports = utils; /***/ }), -/* 802 */ +/* 801 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -93230,14 +91928,14 @@ module.exports = utils; */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(803); + module.exports = __webpack_require__(802); } else { - module.exports = __webpack_require__(806); + module.exports = __webpack_require__(805); } /***/ }), -/* 803 */ +/* 802 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -93246,7 +91944,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(804); +exports = module.exports = __webpack_require__(803); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -93428,7 +92126,7 @@ function localstorage() { /***/ }), -/* 804 */ +/* 803 */ /***/ (function(module, exports, __webpack_require__) { @@ -93444,7 +92142,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(805); +exports.humanize = __webpack_require__(804); /** * The currently active debug mode names, and names to skip. @@ -93636,7 +92334,7 @@ function coerce(val) { /***/ }), -/* 805 */ +/* 804 */ /***/ (function(module, exports) { /** @@ -93794,7 +92492,7 @@ function plural(ms, n, name) { /***/ }), -/* 806 */ +/* 805 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -93810,7 +92508,7 @@ var util = __webpack_require__(29); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(804); +exports = module.exports = __webpack_require__(803); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -93989,7 +92687,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(807); + var net = __webpack_require__(806); stream = new net.Socket({ fd: fd, readable: false, @@ -94048,13 +92746,13 @@ exports.enable(load()); /***/ }), -/* 807 */ +/* 806 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 808 */ +/* 807 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -94064,9 +92762,9 @@ module.exports = require("net"); * Module dependencies */ -exports.extend = __webpack_require__(739); -exports.SourceMap = __webpack_require__(809); -exports.sourceMapResolve = __webpack_require__(820); +exports.extend = __webpack_require__(738); +exports.SourceMap = __webpack_require__(808); +exports.sourceMapResolve = __webpack_require__(819); /** * Convert backslash in the given string to forward slashes @@ -94109,7 +92807,7 @@ exports.last = function(arr, n) { /***/ }), -/* 809 */ +/* 808 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -94117,13 +92815,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(810).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(816).SourceMapConsumer; -exports.SourceNode = __webpack_require__(819).SourceNode; +exports.SourceMapGenerator = __webpack_require__(809).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(815).SourceMapConsumer; +exports.SourceNode = __webpack_require__(818).SourceNode; /***/ }), -/* 810 */ +/* 809 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -94133,10 +92831,10 @@ exports.SourceNode = __webpack_require__(819).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(811); -var util = __webpack_require__(813); -var ArraySet = __webpack_require__(814).ArraySet; -var MappingList = __webpack_require__(815).MappingList; +var base64VLQ = __webpack_require__(810); +var util = __webpack_require__(812); +var ArraySet = __webpack_require__(813).ArraySet; +var MappingList = __webpack_require__(814).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -94545,7 +93243,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 811 */ +/* 810 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -94585,7 +93283,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(812); +var base64 = __webpack_require__(811); // A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, @@ -94691,7 +93389,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 812 */ +/* 811 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -94764,7 +93462,7 @@ exports.decode = function (charCode) { /***/ }), -/* 813 */ +/* 812 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95187,7 +93885,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 814 */ +/* 813 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95197,7 +93895,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(813); +var util = __webpack_require__(812); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -95314,7 +94012,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 815 */ +/* 814 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95324,7 +94022,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(813); +var util = __webpack_require__(812); /** * Determine whether mappingB is after mappingA with respect to generated @@ -95399,7 +94097,7 @@ exports.MappingList = MappingList; /***/ }), -/* 816 */ +/* 815 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -95409,11 +94107,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(813); -var binarySearch = __webpack_require__(817); -var ArraySet = __webpack_require__(814).ArraySet; -var base64VLQ = __webpack_require__(811); -var quickSort = __webpack_require__(818).quickSort; +var util = __webpack_require__(812); +var binarySearch = __webpack_require__(816); +var ArraySet = __webpack_require__(813).ArraySet; +var base64VLQ = __webpack_require__(810); +var quickSort = __webpack_require__(817).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -96487,7 +95185,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 817 */ +/* 816 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -96604,7 +95302,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 818 */ +/* 817 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -96724,7 +95422,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 819 */ +/* 818 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -96734,8 +95432,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(810).SourceMapGenerator; -var util = __webpack_require__(813); +var SourceMapGenerator = __webpack_require__(809).SourceMapGenerator; +var util = __webpack_require__(812); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -97143,17 +95841,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 820 */ +/* 819 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(821) -var resolveUrl = __webpack_require__(822) -var decodeUriComponent = __webpack_require__(823) -var urix = __webpack_require__(825) -var atob = __webpack_require__(826) +var sourceMappingURL = __webpack_require__(820) +var resolveUrl = __webpack_require__(821) +var decodeUriComponent = __webpack_require__(822) +var urix = __webpack_require__(824) +var atob = __webpack_require__(825) @@ -97451,7 +96149,7 @@ module.exports = { /***/ }), -/* 821 */ +/* 820 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -97514,7 +96212,7 @@ void (function(root, factory) { /***/ }), -/* 822 */ +/* 821 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -97532,13 +96230,13 @@ module.exports = resolveUrl /***/ }), -/* 823 */ +/* 822 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(824) +var decodeUriComponent = __webpack_require__(823) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -97549,7 +96247,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 824 */ +/* 823 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -97650,7 +96348,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 825 */ +/* 824 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -97673,7 +96371,7 @@ module.exports = urix /***/ }), -/* 826 */ +/* 825 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -97687,7 +96385,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 827 */ +/* 826 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -97695,8 +96393,8 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(23); var path = __webpack_require__(16); -var define = __webpack_require__(731); -var utils = __webpack_require__(808); +var define = __webpack_require__(730); +var utils = __webpack_require__(807); /** * Expose `mixin()`. @@ -97839,19 +96537,19 @@ exports.comment = function(node) { /***/ }), -/* 828 */ +/* 827 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(800); +var use = __webpack_require__(799); var util = __webpack_require__(29); -var Cache = __webpack_require__(829); -var define = __webpack_require__(731); -var debug = __webpack_require__(802)('snapdragon:parser'); -var Position = __webpack_require__(830); -var utils = __webpack_require__(808); +var Cache = __webpack_require__(828); +var define = __webpack_require__(730); +var debug = __webpack_require__(801)('snapdragon:parser'); +var Position = __webpack_require__(829); +var utils = __webpack_require__(807); /** * Create a new `Parser` with the given `input` and `options`. @@ -98379,7 +97077,7 @@ module.exports = Parser; /***/ }), -/* 829 */ +/* 828 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -98486,13 +97184,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 830 */ +/* 829 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(731); +var define = __webpack_require__(730); /** * Store position for a node @@ -98507,16 +97205,16 @@ module.exports = function Position(start, parser) { /***/ }), -/* 831 */ +/* 830 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var safe = __webpack_require__(832); -var define = __webpack_require__(838); -var extend = __webpack_require__(839); -var not = __webpack_require__(841); +var safe = __webpack_require__(831); +var define = __webpack_require__(837); +var extend = __webpack_require__(838); +var not = __webpack_require__(840); var MAX_LENGTH = 1024 * 64; /** @@ -98669,10 +97367,10 @@ module.exports.makeRe = makeRe; /***/ }), -/* 832 */ +/* 831 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(833); +var parse = __webpack_require__(832); var types = parse.types; module.exports = function (re, opts) { @@ -98718,13 +97416,13 @@ function isRegExp (x) { /***/ }), -/* 833 */ +/* 832 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(834); -var types = __webpack_require__(835); -var sets = __webpack_require__(836); -var positions = __webpack_require__(837); +var util = __webpack_require__(833); +var types = __webpack_require__(834); +var sets = __webpack_require__(835); +var positions = __webpack_require__(836); module.exports = function(regexpStr) { @@ -99006,11 +97704,11 @@ module.exports.types = types; /***/ }), -/* 834 */ +/* 833 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(835); -var sets = __webpack_require__(836); +var types = __webpack_require__(834); +var sets = __webpack_require__(835); // All of these are private and only used by randexp. @@ -99123,7 +97821,7 @@ exports.error = function(regexp, msg) { /***/ }), -/* 835 */ +/* 834 */ /***/ (function(module, exports) { module.exports = { @@ -99139,10 +97837,10 @@ module.exports = { /***/ }), -/* 836 */ +/* 835 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(835); +var types = __webpack_require__(834); var INTS = function() { return [{ type: types.RANGE , from: 48, to: 57 }]; @@ -99227,10 +97925,10 @@ exports.anyChar = function() { /***/ }), -/* 837 */ +/* 836 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(835); +var types = __webpack_require__(834); exports.wordBoundary = function() { return { type: types.POSITION, value: 'b' }; @@ -99250,7 +97948,7 @@ exports.end = function() { /***/ }), -/* 838 */ +/* 837 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99263,8 +97961,8 @@ exports.end = function() { -var isobject = __webpack_require__(749); -var isDescriptor = __webpack_require__(761); +var isobject = __webpack_require__(748); +var isDescriptor = __webpack_require__(760); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -99295,14 +97993,14 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 839 */ +/* 838 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(840); -var assignSymbols = __webpack_require__(750); +var isExtendable = __webpack_require__(839); +var assignSymbols = __webpack_require__(749); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -99362,7 +98060,7 @@ function isEnum(obj, key) { /***/ }), -/* 840 */ +/* 839 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99375,7 +98073,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(748); +var isPlainObject = __webpack_require__(747); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -99383,14 +98081,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 841 */ +/* 840 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(839); -var safe = __webpack_require__(832); +var extend = __webpack_require__(838); +var safe = __webpack_require__(831); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -99462,14 +98160,14 @@ module.exports = toRegex; /***/ }), -/* 842 */ +/* 841 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(843); -var extglob = __webpack_require__(858); +var nanomatch = __webpack_require__(842); +var extglob = __webpack_require__(857); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -99546,7 +98244,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 843 */ +/* 842 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -99557,17 +98255,17 @@ function escapeExtglobs(compiler) { */ var util = __webpack_require__(29); -var toRegex = __webpack_require__(730); -var extend = __webpack_require__(844); +var toRegex = __webpack_require__(729); +var extend = __webpack_require__(843); /** * Local dependencies */ -var compilers = __webpack_require__(846); -var parsers = __webpack_require__(847); -var cache = __webpack_require__(850); -var utils = __webpack_require__(852); +var compilers = __webpack_require__(845); +var parsers = __webpack_require__(846); +var cache = __webpack_require__(849); +var utils = __webpack_require__(851); var MAX_LENGTH = 1024 * 64; /** @@ -100391,14 +99089,14 @@ module.exports = nanomatch; /***/ }), -/* 844 */ +/* 843 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(845); -var assignSymbols = __webpack_require__(750); +var isExtendable = __webpack_require__(844); +var assignSymbols = __webpack_require__(749); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -100458,7 +99156,7 @@ function isEnum(obj, key) { /***/ }), -/* 845 */ +/* 844 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100471,7 +99169,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(748); +var isPlainObject = __webpack_require__(747); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -100479,7 +99177,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 846 */ +/* 845 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -100825,15 +99523,15 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 847 */ +/* 846 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regexNot = __webpack_require__(741); -var toRegex = __webpack_require__(730); -var isOdd = __webpack_require__(848); +var regexNot = __webpack_require__(740); +var toRegex = __webpack_require__(729); +var isOdd = __webpack_require__(847); /** * Characters to use in negation regex (we want to "not" match @@ -101219,7 +99917,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 848 */ +/* 847 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101232,7 +99930,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(849); +var isNumber = __webpack_require__(848); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -101246,7 +99944,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 849 */ +/* 848 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101274,14 +99972,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 850 */ +/* 849 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(851))(); +module.exports = new (__webpack_require__(850))(); /***/ }), -/* 851 */ +/* 850 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101294,7 +99992,7 @@ module.exports = new (__webpack_require__(851))(); -var MapCache = __webpack_require__(829); +var MapCache = __webpack_require__(828); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -101416,7 +100114,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 852 */ +/* 851 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101429,14 +100127,14 @@ var path = __webpack_require__(16); * Module dependencies */ -var isWindows = __webpack_require__(853)(); -var Snapdragon = __webpack_require__(769); -utils.define = __webpack_require__(854); -utils.diff = __webpack_require__(855); -utils.extend = __webpack_require__(844); -utils.pick = __webpack_require__(856); -utils.typeOf = __webpack_require__(857); -utils.unique = __webpack_require__(742); +var isWindows = __webpack_require__(852)(); +var Snapdragon = __webpack_require__(768); +utils.define = __webpack_require__(853); +utils.diff = __webpack_require__(854); +utils.extend = __webpack_require__(843); +utils.pick = __webpack_require__(855); +utils.typeOf = __webpack_require__(856); +utils.unique = __webpack_require__(741); /** * Returns true if the given value is effectively an empty string @@ -101802,7 +100500,7 @@ utils.unixify = function(options) { /***/ }), -/* 853 */ +/* 852 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -101830,7 +100528,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 854 */ +/* 853 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101843,8 +100541,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ -var isobject = __webpack_require__(749); -var isDescriptor = __webpack_require__(761); +var isobject = __webpack_require__(748); +var isDescriptor = __webpack_require__(760); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -101875,7 +100573,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 855 */ +/* 854 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101929,7 +100627,7 @@ function diffArray(one, two) { /***/ }), -/* 856 */ +/* 855 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -101942,7 +100640,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(749); +var isObject = __webpack_require__(748); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -101971,7 +100669,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 857 */ +/* 856 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -102106,7 +100804,7 @@ function isBuffer(val) { /***/ }), -/* 858 */ +/* 857 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102116,18 +100814,18 @@ function isBuffer(val) { * Module dependencies */ -var extend = __webpack_require__(739); -var unique = __webpack_require__(742); -var toRegex = __webpack_require__(730); +var extend = __webpack_require__(738); +var unique = __webpack_require__(741); +var toRegex = __webpack_require__(729); /** * Local dependencies */ -var compilers = __webpack_require__(859); -var parsers = __webpack_require__(870); -var Extglob = __webpack_require__(873); -var utils = __webpack_require__(872); +var compilers = __webpack_require__(858); +var parsers = __webpack_require__(869); +var Extglob = __webpack_require__(872); +var utils = __webpack_require__(871); var MAX_LENGTH = 1024 * 64; /** @@ -102444,13 +101142,13 @@ module.exports = extglob; /***/ }), -/* 859 */ +/* 858 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(860); +var brackets = __webpack_require__(859); /** * Extglob compilers @@ -102620,7 +101318,7 @@ module.exports = function(extglob) { /***/ }), -/* 860 */ +/* 859 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102630,17 +101328,17 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(861); -var parsers = __webpack_require__(863); +var compilers = __webpack_require__(860); +var parsers = __webpack_require__(862); /** * Module dependencies */ -var debug = __webpack_require__(865)('expand-brackets'); -var extend = __webpack_require__(739); -var Snapdragon = __webpack_require__(769); -var toRegex = __webpack_require__(730); +var debug = __webpack_require__(864)('expand-brackets'); +var extend = __webpack_require__(738); +var Snapdragon = __webpack_require__(768); +var toRegex = __webpack_require__(729); /** * Parses the given POSIX character class `pattern` and returns a @@ -102838,13 +101536,13 @@ module.exports = brackets; /***/ }), -/* 861 */ +/* 860 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(862); +var posix = __webpack_require__(861); module.exports = function(brackets) { brackets.compiler @@ -102932,7 +101630,7 @@ module.exports = function(brackets) { /***/ }), -/* 862 */ +/* 861 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -102961,14 +101659,14 @@ module.exports = { /***/ }), -/* 863 */ +/* 862 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(864); -var define = __webpack_require__(731); +var utils = __webpack_require__(863); +var define = __webpack_require__(730); /** * Text regex @@ -103187,14 +101885,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 864 */ +/* 863 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var toRegex = __webpack_require__(730); -var regexNot = __webpack_require__(741); +var toRegex = __webpack_require__(729); +var regexNot = __webpack_require__(740); var cached; /** @@ -103228,7 +101926,7 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 865 */ +/* 864 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -103237,14 +101935,14 @@ exports.createRegex = function(pattern, include) { */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(866); + module.exports = __webpack_require__(865); } else { - module.exports = __webpack_require__(869); + module.exports = __webpack_require__(868); } /***/ }), -/* 866 */ +/* 865 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -103253,7 +101951,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(867); +exports = module.exports = __webpack_require__(866); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -103435,7 +102133,7 @@ function localstorage() { /***/ }), -/* 867 */ +/* 866 */ /***/ (function(module, exports, __webpack_require__) { @@ -103451,7 +102149,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(868); +exports.humanize = __webpack_require__(867); /** * The currently active debug mode names, and names to skip. @@ -103643,7 +102341,7 @@ function coerce(val) { /***/ }), -/* 868 */ +/* 867 */ /***/ (function(module, exports) { /** @@ -103801,7 +102499,7 @@ function plural(ms, n, name) { /***/ }), -/* 869 */ +/* 868 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -103817,7 +102515,7 @@ var util = __webpack_require__(29); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(867); +exports = module.exports = __webpack_require__(866); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -103996,7 +102694,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(807); + var net = __webpack_require__(806); stream = new net.Socket({ fd: fd, readable: false, @@ -104055,15 +102753,15 @@ exports.enable(load()); /***/ }), -/* 870 */ +/* 869 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(860); -var define = __webpack_require__(871); -var utils = __webpack_require__(872); +var brackets = __webpack_require__(859); +var define = __webpack_require__(870); +var utils = __webpack_require__(871); /** * Characters to use in text regex (we want to "not" match @@ -104218,7 +102916,7 @@ module.exports = parsers; /***/ }), -/* 871 */ +/* 870 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104231,7 +102929,7 @@ module.exports = parsers; -var isDescriptor = __webpack_require__(761); +var isDescriptor = __webpack_require__(760); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -104256,14 +102954,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 872 */ +/* 871 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regex = __webpack_require__(741); -var Cache = __webpack_require__(851); +var regex = __webpack_require__(740); +var Cache = __webpack_require__(850); /** * Utils @@ -104332,7 +103030,7 @@ utils.createRegex = function(str) { /***/ }), -/* 873 */ +/* 872 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104342,16 +103040,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(769); -var define = __webpack_require__(871); -var extend = __webpack_require__(739); +var Snapdragon = __webpack_require__(768); +var define = __webpack_require__(870); +var extend = __webpack_require__(738); /** * Local dependencies */ -var compilers = __webpack_require__(859); -var parsers = __webpack_require__(870); +var compilers = __webpack_require__(858); +var parsers = __webpack_require__(869); /** * Customize Snapdragon parser and renderer @@ -104417,16 +103115,16 @@ module.exports = Extglob; /***/ }), -/* 874 */ +/* 873 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(858); -var nanomatch = __webpack_require__(843); -var regexNot = __webpack_require__(741); -var toRegex = __webpack_require__(831); +var extglob = __webpack_require__(857); +var nanomatch = __webpack_require__(842); +var regexNot = __webpack_require__(740); +var toRegex = __webpack_require__(830); var not; /** @@ -104507,14 +103205,14 @@ function textRegex(pattern) { /***/ }), -/* 875 */ +/* 874 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(851))(); +module.exports = new (__webpack_require__(850))(); /***/ }), -/* 876 */ +/* 875 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104527,13 +103225,13 @@ var path = __webpack_require__(16); * Module dependencies */ -var Snapdragon = __webpack_require__(769); -utils.define = __webpack_require__(838); -utils.diff = __webpack_require__(855); -utils.extend = __webpack_require__(839); -utils.pick = __webpack_require__(856); -utils.typeOf = __webpack_require__(877); -utils.unique = __webpack_require__(742); +var Snapdragon = __webpack_require__(768); +utils.define = __webpack_require__(837); +utils.diff = __webpack_require__(854); +utils.extend = __webpack_require__(838); +utils.pick = __webpack_require__(855); +utils.typeOf = __webpack_require__(876); +utils.unique = __webpack_require__(741); /** * Returns true if the platform is windows, or `path.sep` is `\\`. @@ -104830,7 +103528,7 @@ utils.unixify = function(options) { /***/ }), -/* 877 */ +/* 876 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -104965,7 +103663,7 @@ function isBuffer(val) { /***/ }), -/* 878 */ +/* 877 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -104984,9 +103682,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(879); -var reader_1 = __webpack_require__(892); -var fs_stream_1 = __webpack_require__(896); +var readdir = __webpack_require__(878); +var reader_1 = __webpack_require__(891); +var fs_stream_1 = __webpack_require__(895); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -105047,15 +103745,15 @@ exports.default = ReaderAsync; /***/ }), -/* 879 */ +/* 878 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(880); -const readdirAsync = __webpack_require__(888); -const readdirStream = __webpack_require__(891); +const readdirSync = __webpack_require__(879); +const readdirAsync = __webpack_require__(887); +const readdirStream = __webpack_require__(890); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -105139,7 +103837,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 880 */ +/* 879 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105147,11 +103845,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(881); +const DirectoryReader = __webpack_require__(880); let syncFacade = { - fs: __webpack_require__(886), - forEach: __webpack_require__(887), + fs: __webpack_require__(885), + forEach: __webpack_require__(886), sync: true }; @@ -105180,7 +103878,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 881 */ +/* 880 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -105189,9 +103887,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(27).Readable; const EventEmitter = __webpack_require__(379).EventEmitter; const path = __webpack_require__(16); -const normalizeOptions = __webpack_require__(882); -const stat = __webpack_require__(884); -const call = __webpack_require__(885); +const normalizeOptions = __webpack_require__(881); +const stat = __webpack_require__(883); +const call = __webpack_require__(884); /** * Asynchronously reads the contents of a directory and streams the results @@ -105567,14 +104265,14 @@ module.exports = DirectoryReader; /***/ }), -/* 882 */ +/* 881 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const globToRegExp = __webpack_require__(883); +const globToRegExp = __webpack_require__(882); module.exports = normalizeOptions; @@ -105751,7 +104449,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 883 */ +/* 882 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -105888,13 +104586,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 884 */ +/* 883 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(885); +const call = __webpack_require__(884); module.exports = stat; @@ -105969,7 +104667,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 885 */ +/* 884 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106030,14 +104728,14 @@ function callOnce (fn) { /***/ }), -/* 886 */ +/* 885 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const call = __webpack_require__(885); +const call = __webpack_require__(884); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -106101,7 +104799,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 887 */ +/* 886 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106130,7 +104828,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 888 */ +/* 887 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106138,12 +104836,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(889); -const DirectoryReader = __webpack_require__(881); +const maybe = __webpack_require__(888); +const DirectoryReader = __webpack_require__(880); let asyncFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(890), + forEach: __webpack_require__(889), async: true }; @@ -106185,7 +104883,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 889 */ +/* 888 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106212,7 +104910,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 890 */ +/* 889 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106248,7 +104946,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 891 */ +/* 890 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106256,11 +104954,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(881); +const DirectoryReader = __webpack_require__(880); let streamFacade = { fs: __webpack_require__(23), - forEach: __webpack_require__(890), + forEach: __webpack_require__(889), async: true }; @@ -106280,16 +104978,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 892 */ +/* 891 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(16); -var deep_1 = __webpack_require__(893); -var entry_1 = __webpack_require__(895); -var pathUtil = __webpack_require__(894); +var deep_1 = __webpack_require__(892); +var entry_1 = __webpack_require__(894); +var pathUtil = __webpack_require__(893); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -106355,14 +105053,14 @@ exports.default = Reader; /***/ }), -/* 893 */ +/* 892 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(894); -var patternUtils = __webpack_require__(723); +var pathUtils = __webpack_require__(893); +var patternUtils = __webpack_require__(722); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -106445,7 +105143,7 @@ exports.default = DeepFilter; /***/ }), -/* 894 */ +/* 893 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106476,14 +105174,14 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 895 */ +/* 894 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(894); -var patternUtils = __webpack_require__(723); +var pathUtils = __webpack_require__(893); +var patternUtils = __webpack_require__(722); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { this.options = options; @@ -106568,7 +105266,7 @@ exports.default = EntryFilter; /***/ }), -/* 896 */ +/* 895 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106588,8 +105286,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(27); -var fsStat = __webpack_require__(897); -var fs_1 = __webpack_require__(901); +var fsStat = __webpack_require__(896); +var fs_1 = __webpack_require__(900); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -106639,14 +105337,14 @@ exports.default = FileSystemStream; /***/ }), -/* 897 */ +/* 896 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(898); -const statProvider = __webpack_require__(900); +const optionsManager = __webpack_require__(897); +const statProvider = __webpack_require__(899); /** * Asynchronous API. */ @@ -106677,13 +105375,13 @@ exports.statSync = statSync; /***/ }), -/* 898 */ +/* 897 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(899); +const fsAdapter = __webpack_require__(898); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -106696,7 +105394,7 @@ exports.prepare = prepare; /***/ }), -/* 899 */ +/* 898 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106719,7 +105417,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 900 */ +/* 899 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106771,7 +105469,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 901 */ +/* 900 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106802,7 +105500,7 @@ exports.default = FileSystem; /***/ }), -/* 902 */ +/* 901 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106822,9 +105520,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(27); -var readdir = __webpack_require__(879); -var reader_1 = __webpack_require__(892); -var fs_stream_1 = __webpack_require__(896); +var readdir = __webpack_require__(878); +var reader_1 = __webpack_require__(891); +var fs_stream_1 = __webpack_require__(895); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -106892,7 +105590,7 @@ exports.default = ReaderStream; /***/ }), -/* 903 */ +/* 902 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106911,9 +105609,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(879); -var reader_1 = __webpack_require__(892); -var fs_sync_1 = __webpack_require__(904); +var readdir = __webpack_require__(878); +var reader_1 = __webpack_require__(891); +var fs_sync_1 = __webpack_require__(903); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -106973,7 +105671,7 @@ exports.default = ReaderSync; /***/ }), -/* 904 */ +/* 903 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -106992,8 +105690,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(897); -var fs_1 = __webpack_require__(901); +var fsStat = __webpack_require__(896); +var fs_1 = __webpack_require__(900); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -107039,7 +105737,7 @@ exports.default = FileSystemSync; /***/ }), -/* 905 */ +/* 904 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -107055,13 +105753,13 @@ exports.flatten = flatten; /***/ }), -/* 906 */ +/* 905 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var merge2 = __webpack_require__(591); +var merge2 = __webpack_require__(590); /** * Merge multiple streams and propagate their errors into one stream in parallel. */ @@ -107076,13 +105774,13 @@ exports.merge = merge; /***/ }), -/* 907 */ +/* 906 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); -const pathType = __webpack_require__(908); +const pathType = __webpack_require__(907); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -107148,13 +105846,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 908 */ +/* 907 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); -const pify = __webpack_require__(909); +const pify = __webpack_require__(908); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -107197,7 +105895,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 909 */ +/* 908 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -107288,17 +105986,17 @@ module.exports = (obj, opts) => { /***/ }), -/* 910 */ +/* 909 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(23); const path = __webpack_require__(16); -const fastGlob = __webpack_require__(719); -const gitIgnore = __webpack_require__(911); -const pify = __webpack_require__(912); -const slash = __webpack_require__(913); +const fastGlob = __webpack_require__(718); +const gitIgnore = __webpack_require__(910); +const pify = __webpack_require__(911); +const slash = __webpack_require__(912); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -107396,7 +106094,7 @@ module.exports.sync = options => { /***/ }), -/* 911 */ +/* 910 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -107865,7 +106563,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 912 */ +/* 911 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -107940,7 +106638,7 @@ module.exports = (input, options) => { /***/ }), -/* 913 */ +/* 912 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -107958,17 +106656,17 @@ module.exports = input => { /***/ }), -/* 914 */ +/* 913 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(16); const {constants: fsConstants} = __webpack_require__(23); -const pEvent = __webpack_require__(915); -const CpFileError = __webpack_require__(918); -const fs = __webpack_require__(922); -const ProgressEmitter = __webpack_require__(925); +const pEvent = __webpack_require__(914); +const CpFileError = __webpack_require__(917); +const fs = __webpack_require__(921); +const ProgressEmitter = __webpack_require__(924); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -108082,12 +106780,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 915 */ +/* 914 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(916); +const pTimeout = __webpack_require__(915); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -108378,12 +107076,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 916 */ +/* 915 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(917); +const pFinally = __webpack_require__(916); class TimeoutError extends Error { constructor(message) { @@ -108429,7 +107127,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 917 */ +/* 916 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -108451,12 +107149,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 918 */ +/* 917 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(919); +const NestedError = __webpack_require__(918); class CpFileError extends NestedError { constructor(message, nested) { @@ -108470,10 +107168,10 @@ module.exports = CpFileError; /***/ }), -/* 919 */ +/* 918 */ /***/ (function(module, exports, __webpack_require__) { -var inherits = __webpack_require__(920); +var inherits = __webpack_require__(919); var NestedError = function (message, nested) { this.nested = nested; @@ -108524,7 +107222,7 @@ module.exports = NestedError; /***/ }), -/* 920 */ +/* 919 */ /***/ (function(module, exports, __webpack_require__) { try { @@ -108532,12 +107230,12 @@ try { if (typeof util.inherits !== 'function') throw ''; module.exports = util.inherits; } catch (e) { - module.exports = __webpack_require__(921); + module.exports = __webpack_require__(920); } /***/ }), -/* 921 */ +/* 920 */ /***/ (function(module, exports) { if (typeof Object.create === 'function') { @@ -108566,16 +107264,16 @@ if (typeof Object.create === 'function') { /***/ }), -/* 922 */ +/* 921 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(29); const fs = __webpack_require__(22); -const makeDir = __webpack_require__(923); -const pEvent = __webpack_require__(915); -const CpFileError = __webpack_require__(918); +const makeDir = __webpack_require__(922); +const pEvent = __webpack_require__(914); +const CpFileError = __webpack_require__(917); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -108672,7 +107370,7 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 923 */ +/* 922 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -108680,7 +107378,7 @@ exports.copyFileSync = (source, destination, flags) => { const fs = __webpack_require__(23); const path = __webpack_require__(16); const {promisify} = __webpack_require__(29); -const semver = __webpack_require__(924); +const semver = __webpack_require__(923); const defaults = { mode: 0o777 & (~process.umask()), @@ -108829,7 +107527,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 924 */ +/* 923 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -110431,7 +109129,7 @@ function coerce (version, options) { /***/ }), -/* 925 */ +/* 924 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -110472,7 +109170,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 926 */ +/* 925 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -110518,12 +109216,12 @@ exports.default = module.exports; /***/ }), -/* 927 */ +/* 926 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(928); +const NestedError = __webpack_require__(927); class CpyError extends NestedError { constructor(message, nested) { @@ -110537,7 +109235,7 @@ module.exports = CpyError; /***/ }), -/* 928 */ +/* 927 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(29).inherits; @@ -110593,7 +109291,7 @@ module.exports = NestedError; /***/ }), -/* 929 */ +/* 928 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; diff --git a/x-pack/legacy/plugins/beats_management/public/utils/typed_react.ts b/x-pack/legacy/plugins/beats_management/public/utils/typed_react.ts index dbc0894ab8071..89c0d3d2403c5 100644 --- a/x-pack/legacy/plugins/beats_management/public/utils/typed_react.ts +++ b/x-pack/legacy/plugins/beats_management/public/utils/typed_react.ts @@ -4,58 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { omit } from 'lodash'; import React from 'react'; -import { InferableComponentEnhancerWithProps } from 'react-redux'; export type RendererResult = React.ReactElement | null; export type RendererFunction = (args: RenderArgs) => Result; -export type ChildFunctionRendererProps = { - children: RendererFunction; - initializeOnMount?: boolean; - resetOnUnmount?: boolean; -} & RenderArgs; - -interface ChildFunctionRendererOptions { - onInitialize?: (props: RenderArgs) => void; - onCleanup?: (props: RenderArgs) => void; -} - -export const asChildFunctionRenderer = ( - hoc: InferableComponentEnhancerWithProps, - { onInitialize, onCleanup }: ChildFunctionRendererOptions = {} -) => - hoc( - class ChildFunctionRenderer extends React.Component> { - public displayName = 'ChildFunctionRenderer'; - - public componentDidMount() { - if (this.props.initializeOnMount && onInitialize) { - onInitialize(this.getRendererArgs()); - } - } - - public componentWillUnmount() { - if (this.props.resetOnUnmount && onCleanup) { - onCleanup(this.getRendererArgs()); - } - } - - public render() { - return (this.props.children as ChildFunctionRendererProps['children'])( - this.getRendererArgs() - ); - } - - private getRendererArgs = () => - omit(['children', 'initializeOnMount', 'resetOnUnmount'], this.props) as Pick< - ChildFunctionRendererProps, - keyof InjectedProps - >; - } - ); - export type StateUpdater = ( prevState: Readonly, prevProps: Readonly diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx b/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx index e855a381413eb..e8b772e0f2fbd 100644 --- a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx +++ b/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx @@ -12,6 +12,7 @@ import { WorkpadLoadedWithErrorsMetric, } from './workpad_telemetry'; import { METRIC_TYPE } from '../../../lib/ui_metric'; +import { ResolvedArgType } from '../../../../types'; jest.mock('ui/new_platform'); const trackMetric = jest.fn(); @@ -30,15 +31,15 @@ const mockWorkpad = { }; const resolvedArgsMatchWorkpad = { - '1': {}, - '2': {}, - '3': {}, - '4': {}, - '5': {}, + '1': {} as ResolvedArgType, + '2': {} as ResolvedArgType, + '3': {} as ResolvedArgType, + '4': {} as ResolvedArgType, + '5': {} as ResolvedArgType, }; const resolvedArgsNotMatchWorkpad = { - 'non-matching-id': {}, + 'non-matching-id': {} as ResolvedArgType, }; const pendingCounts = { diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx b/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx index 39ff3f45d602a..5f3f114092e61 100644 --- a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx +++ b/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx @@ -5,7 +5,7 @@ */ import React, { useState, useEffect } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; // @ts-ignore: Local Untyped import { trackCanvasUiMetric, METRIC_TYPE } from '../../../lib/ui_metric'; // @ts-ignore: Local Untyped @@ -23,18 +23,6 @@ const mapStateToProps = (state: any) => ({ telemetryResolvedArgs: getArgs(state), }); -/** - Counts of the loading states of workpad elements -*/ -interface ElementCounts { - /** Count of elements in error state */ - error: number; - /** Count of elements in pending state */ - pending: number; - /** Count of elements in ready state */ - ready: number; -} - // TODO: Build out full workpad types /** Individual Page of a Workpad @@ -61,10 +49,8 @@ interface ResolvedArgs { [keys: string]: any; } -interface ElementsLoadedTelemetryProps { - telemetryElementCounts: ElementCounts; +interface ElementsLoadedTelemetryProps extends PropsFromRedux { workpad: Workpad; - telemetryResolvedArgs: {}; } function areAllElementsInResolvedArgs(workpad: Workpad, resolvedArgs: ResolvedArgs): boolean { @@ -77,13 +63,11 @@ function areAllElementsInResolvedArgs(workpad: Workpad, resolvedArgs: ResolvedAr return workpadElements.every(element => resolvedArgsElements.includes(element)); } -export const withUnconnectedElementsLoadedTelemetry = function

( +export const withUnconnectedElementsLoadedTelemetry =

( Component: React.ComponentType

, trackMetric = trackCanvasUiMetric -): React.FC

{ - return function ElementsLoadedTelemetry( - props: P & ElementsLoadedTelemetryProps - ): React.FunctionComponentElement

{ +) => + function ElementsLoadedTelemetry(props: ElementsLoadedTelemetryProps) { const { telemetryElementCounts, workpad, telemetryResolvedArgs, ...other } = props; const [currentWorkpadId, setWorkpadId] = useState(undefined); @@ -127,11 +111,12 @@ export const withUnconnectedElementsLoadedTelemetry = function

return ; }; -}; -export const withElementsLoadedTelemetry =

( - Component: React.ComponentType

-) => { +const connector = connect(mapStateToProps, {}); + +type PropsFromRedux = ConnectedProps; + +export const withElementsLoadedTelemetry =

(Component: React.ComponentType

) => { const telemetry = withUnconnectedElementsLoadedTelemetry(Component); - return connect(mapStateToProps)(telemetry); + return connector(telemetry); }; diff --git a/x-pack/legacy/plugins/canvas/public/components/router/router.js b/x-pack/legacy/plugins/canvas/public/components/router/router.js index b2e4d540b89d8..40c9c469e5505 100644 --- a/x-pack/legacy/plugins/canvas/public/components/router/router.js +++ b/x-pack/legacy/plugins/canvas/public/components/router/router.js @@ -5,7 +5,6 @@ */ import React from 'react'; -import { isClassComponent } from 'recompose'; import PropTypes from 'prop-types'; import { routerProvider } from '../../lib/router_provider'; import { getAppState } from '../../lib/app_state'; @@ -98,9 +97,6 @@ export class Router extends React.PureComponent { return React.createElement(CanvasLoading, { msg: this.props.loadingMessage }); } - // show the activeComponent - return isClassComponent(this.state.activeComponent) - ? React.createElement(this.state.activeComponent, {}) - : this.state.activeComponent({}); + return ; } } diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/element_settings/index.tsx b/x-pack/legacy/plugins/canvas/public/components/sidebar/element_settings/index.tsx index 7532b43a01054..b5e44b4996537 100644 --- a/x-pack/legacy/plugins/canvas/public/components/sidebar/element_settings/index.tsx +++ b/x-pack/legacy/plugins/canvas/public/components/sidebar/element_settings/index.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ import React from 'react'; -import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { getElementById, getSelectedPage } from '../../../state/selectors/workpad'; import { ElementSettings as Component } from './element_settings'; @@ -33,7 +32,3 @@ const renderIfElement: React.FunctionComponent = props => { export const ElementSettings = connect(mapStateToProps)( renderIfElement ); - -ElementSettings.propTypes = { - selectedElementId: PropTypes.string.isRequired, -}; diff --git a/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.test.tsx b/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.test.tsx index d7cbcf59213be..948f89705a5d5 100644 --- a/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.test.tsx +++ b/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.test.tsx @@ -70,8 +70,9 @@ describe('field_manager', () => { store.dispatch = dispatchSpy; instance = shallow( + // https://github.com/airbnb/enzyme/issues/2176#issuecomment-532361526 - {}} /> + {}} store={store} /> ); @@ -79,6 +80,7 @@ describe('field_manager', () => { instance .find(FieldManager) .dive() + .dive() .dive(); }); diff --git a/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.tsx b/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.tsx index 89b325d737bd5..9bca5b82e58aa 100644 --- a/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.tsx +++ b/x-pack/legacy/plugins/graph/public/components/field_manager/field_manager.tsx @@ -18,6 +18,7 @@ import { selectField, deselectField, GraphState, + GraphStore, } from '../../state_management'; import { WorkspaceField } from '../../types'; @@ -35,6 +36,7 @@ export function FieldManagerComponent(props: { deselectField: (fieldName: string) => void; pickerOpen: boolean; setPickerOpen: (open: boolean) => void; + store?: GraphStore; // only for testing purpose }) { return ( diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_time_controls.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_time_controls.tsx index 5095edd4c715c..3653a6d6bbeae 100644 --- a/x-pack/legacy/plugins/infra/public/components/logging/log_time_controls.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_time_controls.tsx @@ -16,7 +16,7 @@ const noop = () => undefined; interface LogTimeControlsProps { currentTime: number | null; startLiveStreaming: () => any; - stopLiveStreaming: () => any; + stopLiveStreaming: () => void; isLiveStreaming: boolean; jumpToTime: (time: number) => any; } diff --git a/x-pack/legacy/plugins/infra/public/components/waffle/waffle_time_controls.tsx b/x-pack/legacy/plugins/infra/public/components/waffle/waffle_time_controls.tsx index 373cfdce5e2a9..4f840336de8c3 100644 --- a/x-pack/legacy/plugins/infra/public/components/waffle/waffle_time_controls.tsx +++ b/x-pack/legacy/plugins/infra/public/components/waffle/waffle_time_controls.tsx @@ -8,13 +8,14 @@ import { EuiButtonEmpty, EuiDatePicker, EuiFormControlLayout } from '@elastic/eu import { FormattedMessage } from '@kbn/i18n/react'; import moment, { Moment } from 'moment'; import React from 'react'; +import { Action } from 'typescript-fsa'; interface WaffleTimeControlsProps { currentTime: number; isLiveStreaming?: boolean; onChangeTime?: (time: number) => void; - startLiveStreaming?: () => void; - stopLiveStreaming?: () => void; + startLiveStreaming?: (payload: void) => Action; + stopLiveStreaming?: (payload: void) => Action; } export class WaffleTimeControls extends React.Component { diff --git a/x-pack/legacy/plugins/infra/public/utils/redux_context.tsx b/x-pack/legacy/plugins/infra/public/utils/redux_context.tsx index 3bd3d31c745a9..f249d72a6b56f 100644 --- a/x-pack/legacy/plugins/infra/public/utils/redux_context.tsx +++ b/x-pack/legacy/plugins/infra/public/utils/redux_context.tsx @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { connect } from 'react-redux'; +import { useSelector } from 'react-redux'; import React, { createContext } from 'react'; import { State, initialState } from '../store'; export const ReduxStateContext = createContext(initialState); -const withRedux = connect((state: State) => state); -export const ReduxStateContextProvider = withRedux(({ children, ...state }) => { - return {children}; -}); +export const ReduxStateContextProvider = ({ children }: { children: JSX.Element }) => { + const state = useSelector((store: State) => store); + return {children}; +}; diff --git a/x-pack/legacy/plugins/infra/public/utils/typed_react.tsx b/x-pack/legacy/plugins/infra/public/utils/typed_react.tsx index eadf3eb9686b5..d057899ba18be 100644 --- a/x-pack/legacy/plugins/infra/public/utils/typed_react.tsx +++ b/x-pack/legacy/plugins/infra/public/utils/typed_react.tsx @@ -6,7 +6,7 @@ import omit from 'lodash/fp/omit'; import React from 'react'; -import { InferableComponentEnhancerWithProps } from 'react-redux'; +import { InferableComponentEnhancerWithProps, ConnectedComponent } from 'react-redux'; export type RendererResult = React.ReactElement | null; export type RendererFunction = (args: RenderArgs) => Result; @@ -25,7 +25,14 @@ interface ChildFunctionRendererOptions { export const asChildFunctionRenderer = ( hoc: InferableComponentEnhancerWithProps, { onInitialize, onCleanup }: ChildFunctionRendererOptions = {} -) => +): ConnectedComponent< + React.ComponentClass<{}>, + { + children: RendererFunction; + initializeOnMount?: boolean; + resetOnUnmount?: boolean; + } & OwnProps +> => hoc( class ChildFunctionRenderer extends React.Component> { public displayName = 'ChildFunctionRenderer'; @@ -53,7 +60,7 @@ export const asChildFunctionRenderer = ( ChildFunctionRendererProps, keyof InjectedProps >; - } + } as any ); export type StateUpdater = ( diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/index.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/index.js index b3f8ee727dff5..d2b43775c5a49 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/index.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_addpanel/index.js @@ -52,7 +52,7 @@ function mapDispatchToProps(dispatch) { }; } -const connectedFlyOut = connect(mapStateToProps, mapDispatchToProps, null, { withRef: true })( +const connectedFlyOut = connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })( AddLayerPanel ); export { connectedFlyOut as AddLayerPanel }; diff --git a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/index.js b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/index.js index 9148fbdfd2d1e..a2f121a9377fe 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/map/mb/index.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/map/mb/index.js @@ -69,6 +69,6 @@ function mapDispatchToProps(dispatch) { } const connectedMBMapContainer = connect(mapStateToProps, mapDispatchToProps, null, { - withRef: true, + forwardRef: true, })(MBMapContainer); export { connectedMBMapContainer as MBMapContainer }; diff --git a/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/index.js b/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/index.js index 0ae497b480776..1b5bf654822b2 100644 --- a/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/index.js +++ b/x-pack/legacy/plugins/maps/public/connected_components/widget_overlay/layer_control/layer_toc/index.js @@ -21,7 +21,7 @@ function mapStateToProps(state = {}) { }; } -const connectedLayerTOC = connect(mapStateToProps, mapDispatchToProps, null, { withRef: true })( +const connectedLayerTOC = connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true })( LayerTOC ); export { connectedLayerTOC as LayerTOC }; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/population_view/metric_selection.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/population_view/metric_selection.tsx index fe5d3ff0c29fb..70a3d1c7d616c 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/population_view/metric_selection.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/population_view/metric_selection.tsx @@ -48,7 +48,10 @@ export const PopulationDetectors: FC = ({ setIsValid }) => { const [chartSettings, setChartSettings] = useState(defaultChartSettings); const [splitField, setSplitField] = useState(jobCreator.splitField); const [fieldValuesPerDetector, setFieldValuesPerDetector] = useState({}); - const [byFieldsUpdated, setByFieldsUpdated] = useReducer<(s: number) => number>(s => s + 1, 0); + const [byFieldsUpdated, setByFieldsUpdated] = useReducer<(s: number, action: any) => number>( + s => s + 1, + 0 + ); const [pageReady, setPageReady] = useState(false); const updateByFields = () => setByFieldsUpdated(0); diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard.tsx index b63ada4bb535c..6fe27457428b1 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard.tsx @@ -41,13 +41,15 @@ export const Wizard: FC = ({ existingJobsAndGroups, firstWizardStep = WIZARD_STEPS.TIME_RANGE, }) => { - const [jobCreatorUpdated, setJobCreatorUpdate] = useReducer<(s: number) => number>(s => s + 1, 0); - const jobCreatorUpdate = () => setJobCreatorUpdate(jobCreatorUpdated); - - const [jobValidatorUpdated, setJobValidatorUpdate] = useReducer<(s: number) => number>( + const [jobCreatorUpdated, setJobCreatorUpdate] = useReducer<(s: number, action: any) => number>( s => s + 1, 0 ); + const jobCreatorUpdate = () => setJobCreatorUpdate(jobCreatorUpdated); + + const [jobValidatorUpdated, setJobValidatorUpdate] = useReducer< + (s: number, action: any) => number + >(s => s + 1, 0); const jobCreatorContext: JobCreatorContextValue = { jobCreatorUpdated, diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx index f9e6bfcf7c236..72f5a62d0af97 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx @@ -7,7 +7,7 @@ import { defaultTo, noop } from 'lodash/fp'; import React, { useCallback } from 'react'; import { DropResult, DragDropContext } from 'react-beautiful-dnd'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { BeforeCapture } from './drag_drop_context'; @@ -30,7 +30,6 @@ import { interface Props { browserFields: BrowserFields; children: React.ReactNode; - dataProviders?: dragAndDropModel.IdToDataProvider; dispatch: Dispatch; } @@ -59,7 +58,7 @@ const onDragEndHandler = ({ /** * DragDropContextWrapperComponent handles all drag end events */ -export const DragDropContextWrapperComponent = React.memo( +export const DragDropContextWrapperComponent = React.memo( ({ browserFields, children, dataProviders, dispatch }) => { const onDragEnd = useCallback( (result: DropResult) => { @@ -112,7 +111,11 @@ const mapStateToProps = (state: State) => { return { dataProviders }; }; -export const DragDropContextWrapper = connect(mapStateToProps)(DragDropContextWrapperComponent); +const connector = connect(mapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const DragDropContextWrapper = connector(DragDropContextWrapperComponent); DragDropContextWrapper.displayName = 'DragDropContextWrapper'; diff --git a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx index 9672097713a9b..cf958bfd75d3b 100644 --- a/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/legacy/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx @@ -12,9 +12,8 @@ import { DraggableStateSnapshot, Droppable, } from 'react-beautiful-dnd'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; -import { ActionCreator } from 'typescript-fsa'; import { EuiPortal } from '@elastic/eui'; import { dragAndDropActions } from '../../store/drag_and_drop'; @@ -59,16 +58,7 @@ interface OwnProps { truncate?: boolean; } -interface DispatchProps { - registerProvider?: ActionCreator<{ - provider: DataProvider; - }>; - unRegisterProvider?: ActionCreator<{ - id: string; - }>; -} - -type Props = OwnProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; /** * Wraps a draggable component to handle registration / unregistration of the @@ -141,10 +131,16 @@ const DraggableWrapperComponent = React.memo( DraggableWrapperComponent.displayName = 'DraggableWrapperComponent'; -export const DraggableWrapper = connect(null, { +const mapDispatchToProps = { registerProvider: dragAndDropActions.registerProvider, unRegisterProvider: dragAndDropActions.unRegisterProvider, -})(DraggableWrapperComponent); +}; + +const connector = connect(null, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const DraggableWrapper = connector(DraggableWrapperComponent); DraggableWrapper.displayName = 'DraggableWrapper'; diff --git a/x-pack/legacy/plugins/siem/public/components/error_toast_dispatcher/index.tsx b/x-pack/legacy/plugins/siem/public/components/error_toast_dispatcher/index.tsx index 3628330fbd459..ab9170ce1dd6a 100644 --- a/x-pack/legacy/plugins/siem/public/components/error_toast_dispatcher/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/error_toast_dispatcher/index.tsx @@ -5,10 +5,9 @@ */ import { useEffect } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; -import { appModel, appSelectors, State } from '../../store'; +import { appSelectors, State } from '../../store'; import { appActions } from '../../store/app'; import { useStateToaster } from '../toasters'; @@ -16,15 +15,7 @@ interface OwnProps { toastLifeTimeMs?: number; } -interface ReduxProps { - errors?: appModel.Error[]; -} - -interface DispatchProps { - removeError: ActionCreator<{ id: string }>; -} - -type Props = OwnProps & ReduxProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; const ErrorToastDispatcherComponent = ({ toastLifeTimeMs = 5000, @@ -58,6 +49,12 @@ const makeMapStateToProps = () => { return (state: State) => getErrorSelector(state); }; -export const ErrorToastDispatcher = connect(makeMapStateToProps, { +const mapDispatchToProps = { removeError: appActions.removeError, -})(ErrorToastDispatcherComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const ErrorToastDispatcher = connector(ErrorToastDispatcherComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx index c7ccff5bdfcff..1e7c7fc2411bb 100644 --- a/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/events_viewer/index.tsx @@ -6,20 +6,16 @@ import { isEqual } from 'lodash/fp'; import React, { useCallback, useMemo, useEffect } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { inputsModel, inputsSelectors, State, timelineSelectors } from '../../store'; import { inputsActions, timelineActions } from '../../store/actions'; -import { KqlMode, SubsetTimelineModel, TimelineModel } from '../../store/timeline/model'; +import { SubsetTimelineModel, TimelineModel } from '../../store/timeline/model'; import { ColumnHeader } from '../timeline/body/column_headers/column_header'; -import { DataProvider } from '../timeline/data_providers/data_provider'; -import { Sort } from '../timeline/body/sort'; import { OnChangeItemsPerPage } from '../timeline/events'; -import { Filter, Query } from '../../../../../../../src/plugins/data/public'; +import { Filter } from '../../../../../../../src/plugins/data/public'; import { useUiSetting } from '../../lib/kibana'; import { EventsViewer } from './events_viewer'; -import { InputsModelId } from '../../store/inputs/constants'; import { useFetchIndexPatterns } from '../../containers/detection_engine/rules/fetch_index_patterns'; import { TimelineTypeContextProps } from '../timeline/timeline_context'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; @@ -38,51 +34,7 @@ export interface OwnProps { utilityBar?: (refetch: inputsModel.Refetch, totalCount: number) => React.ReactNode; } -interface StateReduxProps { - columns: ColumnHeader[]; - dataProviders?: DataProvider[]; - filters: Filter[]; - isLive: boolean; - itemsPerPage?: number; - itemsPerPageOptions?: number[]; - kqlMode: KqlMode; - deletedEventIds: Readonly; - query: Query; - pageCount?: number; - sort?: Sort; - showCheckboxes: boolean; - showRowRenderers: boolean; -} - -interface DispatchProps { - createTimeline: ActionCreator<{ - id: string; - columns: ColumnHeader[]; - itemsPerPage?: number; - sort?: Sort; - showCheckboxes?: boolean; - showRowRenderers?: boolean; - }>; - deleteEventQuery: ActionCreator<{ - id: string; - inputId: InputsModelId; - }>; - removeColumn: ActionCreator<{ - id: string; - columnId: string; - }>; - updateItemsPerPage: ActionCreator<{ - id: string; - itemsPerPage: number; - }>; - upsertColumn: ActionCreator<{ - column: ColumnHeader; - id: string; - index: number; - }>; -} - -type Props = OwnProps & StateReduxProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; const defaultTimelineTypeContext = { loadingText: i18n.LOADING_EVENTS, @@ -224,13 +176,19 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const StatefulEventsViewer = connect(makeMapStateToProps, { +const mapDispatchToProps = { createTimeline: timelineActions.createTimeline, deleteEventQuery: inputsActions.deleteOneQuery, updateItemsPerPage: timelineActions.updateItemsPerPage, removeColumn: timelineActions.removeColumn, upsertColumn: timelineActions.upsertColumn, -})( +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulEventsViewer = connector( React.memo( StatefulEventsViewerComponent, (prevProps, nextProps) => @@ -245,7 +203,6 @@ export const StatefulEventsViewer = connect(makeMapStateToProps, { isEqual(prevProps.itemsPerPageOptions, nextProps.itemsPerPageOptions) && prevProps.kqlMode === nextProps.kqlMode && isEqual(prevProps.query, nextProps.query) && - prevProps.pageCount === nextProps.pageCount && isEqual(prevProps.sort, nextProps.sort) && prevProps.start === nextProps.start && isEqual(prevProps.pageFilters, nextProps.pageFilters) && diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx index 24e4cd77b20d3..cf9e4f57d67b7 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.test.tsx @@ -6,6 +6,7 @@ import { mount } from 'enzyme'; import React from 'react'; +import { ActionCreator } from 'typescript-fsa'; import { mockBrowserFields } from '../../containers/source/mock'; import { TestProviders } from '../../mock'; @@ -13,6 +14,7 @@ import { TestProviders } from '../../mock'; import { FIELD_BROWSER_HEIGHT, FIELD_BROWSER_WIDTH } from './helpers'; import { StatefulFieldsBrowserComponent } from '.'; +import { ColumnHeader } from '../timeline/body/column_headers/column_header'; // Suppress warnings about "react-beautiful-dnd" until we migrate to @testing-library/react /* eslint-disable no-console */ @@ -27,6 +29,17 @@ afterAll(() => { console.warn = originalWarn; }); +const removeColumnMock = (jest.fn() as unknown) as ActionCreator<{ + id: string; + columnId: string; +}>; + +const upsertColumnMock = (jest.fn() as unknown) as ActionCreator<{ + column: ColumnHeader; + id: string; + index: number; +}>; + describe('StatefulFieldsBrowser', () => { const timelineId = 'test'; @@ -41,6 +54,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -65,6 +80,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -83,6 +100,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -111,6 +130,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -142,6 +163,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -180,6 +203,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -206,6 +231,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); @@ -232,6 +259,8 @@ describe('StatefulFieldsBrowser', () => { timelineId={timelineId} toggleColumn={jest.fn()} width={FIELD_BROWSER_WIDTH} + removeColumn={removeColumnMock} + upsertColumn={upsertColumnMock} /> ); diff --git a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx index c8cde5fa02a51..b545c6890bd41 100644 --- a/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/fields_browser/index.tsx @@ -7,9 +7,8 @@ import { EuiButtonEmpty, EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { noop } from 'lodash/fp'; import React, { useEffect, useRef, useState, useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; -import { ActionCreator } from 'typescript-fsa'; import { BrowserFields } from '../../containers/source'; import { timelineActions } from '../../store/actions'; @@ -31,22 +30,10 @@ const FieldsBrowserButtonContainer = styled.div` FieldsBrowserButtonContainer.displayName = 'FieldsBrowserButtonContainer'; -interface DispatchProps { - removeColumn?: ActionCreator<{ - id: string; - columnId: string; - }>; - upsertColumn?: ActionCreator<{ - column: ColumnHeader; - id: string; - index: number; - }>; -} - /** * Manages the state of the field browser */ -export const StatefulFieldsBrowserComponent = React.memo( +export const StatefulFieldsBrowserComponent = React.memo( ({ columnHeaders, browserFields, @@ -212,7 +199,13 @@ export const StatefulFieldsBrowserComponent = React.memo; + +export const StatefulFieldsBrowser = connector(React.memo(StatefulFieldsBrowserComponent)); diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/header/index.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/header/index.tsx index e1075c89ca350..901f7afd1ed48 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/header/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/header/index.tsx @@ -5,9 +5,8 @@ */ import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; import { isEmpty, get } from 'lodash/fp'; import { History } from '../../../lib/history'; @@ -19,10 +18,9 @@ import { State, timelineSelectors, } from '../../../store'; -import { UpdateNote } from '../../notes/helpers'; import { defaultHeaders } from '../../timeline/body/column_headers/default_headers'; import { Properties } from '../../timeline/properties'; -import { appActions, appModel } from '../../../store/app'; +import { appActions } from '../../../store/app'; import { inputsActions } from '../../../store/inputs'; import { timelineActions } from '../../../store/actions'; import { timelineDefaults, TimelineModel } from '../../../store/timeline/model'; @@ -34,41 +32,7 @@ interface OwnProps { usersViewing: string[]; } -interface StateReduxProps { - description: string; - notesById: appModel.NotesById; - isDataInTimeline: boolean; - isDatepickerLocked: boolean; - isFavorite: boolean; - noteIds: string[]; - title: string; - width: number; -} - -interface DispatchProps { - associateNote: (noteId: string) => void; - applyDeltaToWidth?: ({ - id, - delta, - bodyClientWidthPixels, - maxWidthPercent, - minWidthPixels, - }: { - id: string; - delta: number; - bodyClientWidthPixels: number; - maxWidthPercent: number; - minWidthPixels: number; - }) => void; - createTimeline: ActionCreator<{ id: string; show?: boolean }>; - toggleLock: ActionCreator<{ linkToId: InputsModelId }>; - updateDescription: ActionCreator<{ id: string; description: string }>; - updateIsFavorite: ActionCreator<{ id: string; isFavorite: boolean }>; - updateNote: UpdateNote; - updateTitle: ActionCreator<{ id: string; title: string }>; -} - -type Props = OwnProps & StateReduxProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; const StatefulFlyoutHeader = React.memo( ({ @@ -160,9 +124,7 @@ const makeMapStateToProps = () => { }; const mapDispatchToProps = (dispatch: Dispatch, { timelineId }: OwnProps) => ({ - associateNote: (noteId: string) => { - dispatch(timelineActions.addNote({ id: timelineId, noteId })); - }, + associateNote: (noteId: string) => dispatch(timelineActions.addNote({ id: timelineId, noteId })), applyDeltaToWidth: ({ id, delta, @@ -175,7 +137,7 @@ const mapDispatchToProps = (dispatch: Dispatch, { timelineId }: OwnProps) => ({ bodyClientWidthPixels: number; maxWidthPercent: number; minWidthPixels: number; - }) => { + }) => dispatch( timelineActions.applyDeltaToWidth({ id, @@ -184,35 +146,30 @@ const mapDispatchToProps = (dispatch: Dispatch, { timelineId }: OwnProps) => ({ maxWidthPercent, minWidthPixels, }) - ); - }, - createTimeline: ({ id, show }: { id: string; show?: boolean }) => { + ), + createTimeline: ({ id, show }: { id: string; show?: boolean }) => dispatch( timelineActions.createTimeline({ id, columns: defaultHeaders, show, }) - ); - }, - updateDescription: ({ id, description }: { id: string; description: string }) => { - dispatch(timelineActions.updateDescription({ id, description })); - }, - updateIsFavorite: ({ id, isFavorite }: { id: string; isFavorite: boolean }) => { - dispatch(timelineActions.updateIsFavorite({ id, isFavorite })); - }, - updateIsLive: ({ id, isLive }: { id: string; isLive: boolean }) => { - dispatch(timelineActions.updateIsLive({ id, isLive })); - }, - updateNote: (note: Note) => { - dispatch(appActions.updateNote({ note })); - }, - updateTitle: ({ id, title }: { id: string; title: string }) => { - dispatch(timelineActions.updateTitle({ id, title })); - }, - toggleLock: ({ linkToId }: { linkToId: InputsModelId }) => { - dispatch(inputsActions.toggleTimelineLinkTo({ linkToId })); - }, + ), + updateDescription: ({ id, description }: { id: string; description: string }) => + dispatch(timelineActions.updateDescription({ id, description })), + updateIsFavorite: ({ id, isFavorite }: { id: string; isFavorite: boolean }) => + dispatch(timelineActions.updateIsFavorite({ id, isFavorite })), + updateIsLive: ({ id, isLive }: { id: string; isLive: boolean }) => + dispatch(timelineActions.updateIsLive({ id, isLive })), + updateNote: (note: Note) => dispatch(appActions.updateNote({ note })), + updateTitle: ({ id, title }: { id: string; title: string }) => + dispatch(timelineActions.updateTitle({ id, title })), + toggleLock: ({ linkToId }: { linkToId: InputsModelId }) => + dispatch(inputsActions.toggleTimelineLinkTo({ linkToId })), }); -export const FlyoutHeader = connect(makeMapStateToProps, mapDispatchToProps)(StatefulFlyoutHeader); +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const FlyoutHeader = connector(StatefulFlyoutHeader); diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx index 9fb59e2034b08..d18c22e44ce94 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/index.tsx @@ -7,9 +7,8 @@ import { EuiBadge } from '@elastic/eui'; import { defaultTo, getOr } from 'lodash/fp'; import React from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; -import { ActionCreator } from 'typescript-fsa'; import { State, timelineSelectors } from '../../store'; import { DataProvider } from '../timeline/data_providers/data_provider'; @@ -46,30 +45,7 @@ interface OwnProps { usersViewing: string[]; } -interface DispatchProps { - showTimeline: ActionCreator<{ id: string; show: boolean }>; - applyDeltaToWidth?: ({ - id, - delta, - bodyClientWidthPixels, - maxWidthPercent, - minWidthPixels, - }: { - id: string; - delta: number; - bodyClientWidthPixels: number; - maxWidthPercent: number; - minWidthPixels: number; - }) => void; -} - -interface StateReduxProps { - dataProviders?: DataProvider[]; - show: boolean; - width: number; -} - -type Props = OwnProps & DispatchProps & StateReduxProps; +type Props = OwnProps & ProsFromRedux; export const FlyoutComponent = React.memo( ({ @@ -110,15 +86,21 @@ FlyoutComponent.displayName = 'FlyoutComponent'; const mapStateToProps = (state: State, { timelineId }: OwnProps) => { const timelineById = defaultTo({}, timelineSelectors.timelineByIdSelector(state)); - const dataProviders = getOr([], `${timelineId}.dataProviders`, timelineById); - const show = getOr('false', `${timelineId}.show`, timelineById); - const width = getOr(DEFAULT_TIMELINE_WIDTH, `${timelineId}.width`, timelineById); + const dataProviders = getOr([], `${timelineId}.dataProviders`, timelineById) as DataProvider[]; + const show = getOr(false, `${timelineId}.show`, timelineById) as boolean; + const width = getOr(DEFAULT_TIMELINE_WIDTH, `${timelineId}.width`, timelineById) as number; return { dataProviders, show, width }; }; -export const Flyout = connect(mapStateToProps, { +const mapDispatchToProps = { showTimeline: timelineActions.showTimeline, -})(FlyoutComponent); +}; + +const connector = connect(mapStateToProps, mapDispatchToProps); + +type ProsFromRedux = ConnectedProps; + +export const Flyout = connector(FlyoutComponent); Flyout.displayName = 'Flyout'; diff --git a/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.tsx b/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.tsx index 00ac15092a6ec..fb977417ffbbf 100644 --- a/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/flyout/pane/index.tsx @@ -6,9 +6,8 @@ import { EuiButtonIcon, EuiFlyout, EuiFlyoutBody, EuiFlyoutHeader, EuiToolTip } from '@elastic/eui'; import React, { useCallback, useState } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import styled from 'styled-components'; -import { ActionCreator } from 'typescript-fsa'; import { Resizable, ResizeCallback } from 're-resizable'; import { throttle } from 'lodash/fp'; @@ -30,17 +29,7 @@ interface OwnProps { width: number; } -interface DispatchProps { - applyDeltaToWidth: ActionCreator<{ - id: string; - delta: number; - bodyClientWidthPixels: number; - maxWidthPercent: number; - minWidthPixels: number; - }>; -} - -type Props = OwnProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; const EuiFlyoutContainer = styled.div<{ headerHeight: number }>` .timeline-flyout { @@ -183,8 +172,14 @@ const FlyoutPaneComponent: React.FC = ({ ); }; -export const Pane = connect(null, { +const mapDispatchToProps = { applyDeltaToWidth: timelineActions.applyDeltaToWidth, -})(React.memo(FlyoutPaneComponent)); +}; + +const connector = connect(null, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const Pane = connector(React.memo(FlyoutPaneComponent)); Pane.displayName = 'Pane'; diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts b/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts index 432939b0729d7..61c3d9f73e0d0 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/helpers.ts @@ -6,7 +6,7 @@ import ApolloClient from 'apollo-client'; import { getOr, set } from 'lodash/fp'; -import { ActionCreator } from 'typescript-fsa'; +import { Action } from 'typescript-fsa'; import { Dispatch } from 'redux'; import { oneTimelineQuery } from '../../containers/timeline/one/index.gql_query'; @@ -183,7 +183,13 @@ export interface QueryTimelineById { timelineId: string; onOpenTimeline?: (timeline: TimelineModel) => void; openTimeline?: boolean; - updateIsLoading: ActionCreator<{ id: string; isLoading: boolean }>; + updateIsLoading: ({ + id, + isLoading, + }: { + id: string; + isLoading: boolean; + }) => Action<{ id: string; isLoading: boolean }>; updateTimeline: DispatchUpdateTimeline; } diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx b/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx index a97cfefaf0393..daa64f9f16c83 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/index.tsx @@ -6,7 +6,7 @@ import ApolloClient from 'apollo-client'; import React, { useEffect, useState, useCallback } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { defaultHeaders } from '../../components/timeline/body/column_headers/default_headers'; @@ -39,8 +39,6 @@ import { OpenTimelineResult, OnToggleShowNotes, OnDeleteOneTimeline, - OpenTimelineDispatchProps, - OpenTimelineReduxProps, } from './types'; import { DEFAULT_SORT_FIELD, DEFAULT_SORT_DIRECTION } from './constants'; @@ -55,8 +53,7 @@ interface OwnProps { export type OpenTimelineOwnProps = OwnProps & Pick & - OpenTimelineDispatchProps & - OpenTimelineReduxProps; + PropsFromRedux; /** Returns a collection of selected timeline ids */ export const getSelectedTimelineIds = (selectedItems: OpenTimelineResult[]): string[] => @@ -346,7 +343,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateTimeline: dispatchUpdateTimeline(dispatch), }); -export const StatefulOpenTimeline = connect( - makeMapStateToProps, - mapDispatchToProps -)(StatefulOpenTimelineComponent); +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulOpenTimeline = connector(StatefulOpenTimelineComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/open_timeline/types.ts b/x-pack/legacy/plugins/siem/public/components/open_timeline/types.ts index e5e85ccf0954a..b14bb1cf86d31 100644 --- a/x-pack/legacy/plugins/siem/public/components/open_timeline/types.ts +++ b/x-pack/legacy/plugins/siem/public/components/open_timeline/types.ts @@ -4,11 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ActionCreator } from 'typescript-fsa'; - import { AllTimelinesVariables } from '../../containers/timeline/all'; import { TimelineModel } from '../../store/timeline/model'; -import { ColumnHeader } from '../timeline/body/column_headers/column_header'; import { NoteResult } from '../../graphql/types'; /** The users who added a timeline to favorites */ @@ -163,17 +160,3 @@ export type DispatchUpdateTimeline = ({ timeline, to, }: UpdateTimeline) => () => void; - -export interface OpenTimelineDispatchProps { - updateTimeline: DispatchUpdateTimeline; - createNewTimeline: ActionCreator<{ - id: string; - columns: ColumnHeader[]; - show?: boolean; - }>; - updateIsLoading: ActionCreator<{ id: string; isLoading: boolean }>; -} - -export interface OpenTimelineReduxProps { - timeline: TimelineModel; -} diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx index f5485922647ca..853ba7ae23414 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/authentications_table/index.tsx @@ -8,8 +8,7 @@ import { has } from 'lodash/fp'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { hostsActions } from '../../../../store/hosts'; import { AuthenticationsEdges } from '../../../../graphql/types'; @@ -40,24 +39,6 @@ interface OwnProps { type: hostsModel.HostsType; } -interface AuthenticationTableReduxProps { - activePage: number; - limit: number; -} - -interface AuthenticationTableDispatchProps { - updateTableActivePage: ActionCreator<{ - activePage: number; - hostsType: hostsModel.HostsType; - tableType: hostsModel.HostsTableType; - }>; - updateTableLimit: ActionCreator<{ - limit: number; - hostsType: hostsModel.HostsType; - tableType: hostsModel.HostsTableType; - }>; -} - export type AuthTableColumns = [ Columns, Columns, @@ -70,9 +51,7 @@ export type AuthTableColumns = [ Columns ]; -type AuthenticationTableProps = OwnProps & - AuthenticationTableReduxProps & - AuthenticationTableDispatchProps; +type AuthenticationTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -154,10 +133,16 @@ const makeMapStateToProps = () => { }; }; -export const AuthenticationTable = connect(makeMapStateToProps, { +const mapDispatchToProps = { updateTableActivePage: hostsActions.updateTableActivePage, updateTableLimit: hostsActions.updateTableLimit, -})(AuthenticationTableComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const AuthenticationTable = connector(AuthenticationTableComponent); const getAuthenticationColumns = (): AuthTableColumns => [ { diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.tsx index 79bdf5c4b8315..0f56ef53ac081 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/hosts_table/index.tsx @@ -5,8 +5,7 @@ */ import React, { useMemo, useCallback } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { IIndexPattern } from 'src/plugins/data/public'; import { hostsActions } from '../../../../store/actions'; import { @@ -46,30 +45,6 @@ interface OwnProps { type: hostsModel.HostsType; } -interface HostsTableReduxProps { - activePage: number; - direction: Direction; - limit: number; - sortField: HostsFields; -} - -interface HostsTableDispatchProps { - updateHostsSort: ActionCreator<{ - hostsType: hostsModel.HostsType; - sort: HostsSortField; - }>; - updateTableActivePage: ActionCreator<{ - activePage: number; - hostsType: hostsModel.HostsType; - tableType: hostsModel.HostsTableType; - }>; - updateTableLimit: ActionCreator<{ - hostsType: hostsModel.HostsType; - limit: number; - tableType: hostsModel.HostsTableType; - }>; -} - export type HostsTableColumns = [ Columns, Columns, @@ -77,7 +52,7 @@ export type HostsTableColumns = [ Columns ]; -type HostsTableProps = OwnProps & HostsTableReduxProps & HostsTableDispatchProps; +type HostsTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -217,10 +192,16 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const HostsTable = connect(makeMapStateToProps, { +const mapDispatchToProps = { updateHostsSort: hostsActions.updateHostsSort, updateTableActivePage: hostsActions.updateTableActivePage, updateTableLimit: hostsActions.updateTableLimit, -})(HostsTableComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const HostsTable = connector(HostsTableComponent); HostsTable.displayName = 'HostsTable'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/hosts/uncommon_process_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/hosts/uncommon_process_table/index.tsx index b4c01053f0e9c..12744ddafa396 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/hosts/uncommon_process_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/hosts/uncommon_process_table/index.tsx @@ -7,8 +7,7 @@ /* eslint-disable react/display-name */ import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { hostsActions } from '../../../../store/actions'; import { UncommonProcessesEdges, UncommonProcessItem } from '../../../../graphql/types'; @@ -33,24 +32,6 @@ interface OwnProps { type: hostsModel.HostsType; } -interface UncommonProcessTableReduxProps { - activePage: number; - limit: number; -} - -interface UncommonProcessTableDispatchProps { - updateTableActivePage: ActionCreator<{ - activePage: number; - hostsType: hostsModel.HostsType; - tableType: hostsModel.HostsTableType; - }>; - updateTableLimit: ActionCreator<{ - limit: number; - hostsType: hostsModel.HostsType; - tableType: hostsModel.HostsTableType; - }>; -} - export type UncommonProcessTableColumns = [ Columns, Columns, @@ -60,9 +41,7 @@ export type UncommonProcessTableColumns = [ Columns ]; -type UncommonProcessTableProps = OwnProps & - UncommonProcessTableReduxProps & - UncommonProcessTableDispatchProps; +type UncommonProcessTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -150,10 +129,16 @@ const makeMapStateToProps = () => { return (state: State, { type }: OwnProps) => getUncommonProcessesSelector(state, type); }; -export const UncommonProcessTable = connect(makeMapStateToProps, { +const mapDispatchToProps = { updateTableActivePage: hostsActions.updateTableActivePage, updateTableLimit: hostsActions.updateTableLimit, -})(UncommonProcessTableComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const UncommonProcessTable = connector(UncommonProcessTableComponent); UncommonProcessTable.displayName = 'UncommonProcessTable'; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx index e316f951a0363..f3fe98936a55d 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_dns_table/index.tsx @@ -6,8 +6,7 @@ import { isEqual } from 'lodash/fp'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { networkActions } from '../../../../store/actions'; import { @@ -37,22 +36,7 @@ interface OwnProps { type: networkModel.NetworkType; } -interface NetworkDnsTableReduxProps { - activePage: number; - limit: number; - sort: NetworkDnsSortField; - isPtrIncluded: boolean; -} - -interface NetworkDnsTableDispatchProps { - updateNetworkTable: ActionCreator<{ - networkType: networkModel.NetworkType; - tableType: networkModel.AllNetworkTables; - updates: networkModel.TableUpdates; - }>; -} - -type NetworkDnsTableProps = OwnProps & NetworkDnsTableReduxProps & NetworkDnsTableDispatchProps; +type NetworkDnsTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -172,6 +156,12 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const NetworkDnsTable = connect(makeMapStateToProps, { +const mapDispatchToProps = { updateNetworkTable: networkActions.updateNetworkTable, -})(NetworkDnsTableComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const NetworkDnsTable = connector(NetworkDnsTableComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/__snapshots__/index.test.tsx.snap index dfc1b2cf64e38..875a490d86be3 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/__snapshots__/index.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`NetworkHttp Table Component rendering it renders the default NetworkHttp table 1`] = ` - { ); - expect(wrapper.find('Connect(NetworkHttpTableComponent)')).toMatchSnapshot(); + expect(wrapper.find('Connect(Component)')).toMatchSnapshot(); }); }); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx index 58adc971b0101..87038eb6aaeeb 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_http_table/index.tsx @@ -5,17 +5,10 @@ */ import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { networkActions } from '../../../../store/actions'; -import { - Direction, - NetworkHttpEdges, - NetworkHttpFields, - NetworkHttpSortField, -} from '../../../../graphql/types'; +import { Direction, NetworkHttpEdges, NetworkHttpFields } from '../../../../graphql/types'; import { networkModel, networkSelectors, State } from '../../../../store'; import { Criteria, ItemsPerRow, PaginatedTable } from '../../../paginated_table'; @@ -34,21 +27,7 @@ interface OwnProps { type: networkModel.NetworkType; } -interface NetworkHttpTableReduxProps { - activePage: number; - limit: number; - sort: NetworkHttpSortField; -} - -interface NetworkHttpTableDispatchProps { - updateNetworkTable: ActionCreator<{ - networkType: networkModel.NetworkType; - tableType: networkModel.AllNetworkTables; - updates: networkModel.TableUpdates; - }>; -} - -type NetworkHttpTableProps = OwnProps & NetworkHttpTableReduxProps & NetworkHttpTableDispatchProps; +type NetworkHttpTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -61,91 +40,89 @@ const rowItems: ItemsPerRow[] = [ }, ]; -const NetworkHttpTableComponent = React.memo( - ({ - activePage, - data, - fakeTotalCount, - id, - isInspect, - limit, - loading, - loadPage, - showMorePagesIndicator, - sort, - totalCount, - type, - updateNetworkTable, - }) => { - const tableType = - type === networkModel.NetworkType.page - ? networkModel.NetworkTableType.http - : networkModel.IpDetailsTableType.http; - - const updateLimitPagination = useCallback( - newLimit => +const NetworkHttpTableComponent: React.FC = ({ + activePage, + data, + fakeTotalCount, + id, + isInspect, + limit, + loading, + loadPage, + showMorePagesIndicator, + sort, + totalCount, + type, + updateNetworkTable, +}) => { + const tableType = + type === networkModel.NetworkType.page + ? networkModel.NetworkTableType.http + : networkModel.IpDetailsTableType.http; + + const updateLimitPagination = useCallback( + newLimit => + updateNetworkTable({ + networkType: type, + tableType, + updates: { limit: newLimit }, + }), + [type, updateNetworkTable, tableType] + ); + + const updateActivePage = useCallback( + newPage => + updateNetworkTable({ + networkType: type, + tableType, + updates: { activePage: newPage }, + }), + [type, updateNetworkTable, tableType] + ); + + const onChange = useCallback( + (criteria: Criteria) => { + if (criteria.sort != null && criteria.sort.direction !== sort.direction) { updateNetworkTable({ networkType: type, tableType, - updates: { limit: newLimit }, - }), - [type, updateNetworkTable, tableType] - ); - - const updateActivePage = useCallback( - newPage => - updateNetworkTable({ - networkType: type, - tableType, - updates: { activePage: newPage }, - }), - [type, updateNetworkTable, tableType] - ); - - const onChange = useCallback( - (criteria: Criteria) => { - if (criteria.sort != null && criteria.sort.direction !== sort.direction) { - updateNetworkTable({ - networkType: type, - tableType, - updates: { - sort: { - direction: criteria.sort.direction as Direction, - }, + updates: { + sort: { + direction: criteria.sort.direction as Direction, }, - }); - } - }, - [tableType, sort.direction, type, updateNetworkTable] - ); - - const sorting = { field: `node.${NetworkHttpFields.requestCount}`, direction: sort.direction }; - - return ( - - ); - } -); + }, + }); + } + }, + [tableType, sort.direction, type, updateNetworkTable] + ); + + const sorting = { field: `node.${NetworkHttpFields.requestCount}`, direction: sort.direction }; + + return ( + + ); +}; NetworkHttpTableComponent.displayName = 'NetworkHttpTableComponent'; @@ -155,8 +132,12 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const NetworkHttpTable = compose>( - connect(makeMapStateToProps, { - updateNetworkTable: networkActions.updateNetworkTable, - }) -)(NetworkHttpTableComponent); +const mapDispatchToProps = { + updateNetworkTable: networkActions.updateNetworkTable, +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const NetworkHttpTable = connector(React.memo(NetworkHttpTableComponent)); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_countries_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_countries_table/index.tsx index 6d14b52d3586d..37355a37fa6d7 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_countries_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_countries_table/index.tsx @@ -6,9 +6,7 @@ import { isEqual, last } from 'lodash/fp'; import React, { useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { IIndexPattern } from 'src/plugins/data/public'; import { networkActions } from '../../../../store/actions'; @@ -39,23 +37,7 @@ interface OwnProps { type: networkModel.NetworkType; } -interface NetworkTopCountriesTableReduxProps { - activePage: number; - limit: number; - sort: NetworkTopTablesSortField; -} - -interface NetworkTopCountriesTableDispatchProps { - updateNetworkTable: ActionCreator<{ - networkType: networkModel.NetworkType; - tableType: networkModel.AllNetworkTables; - updates: networkModel.TableUpdates; - }>; -} - -type NetworkTopCountriesTableProps = OwnProps & - NetworkTopCountriesTableReduxProps & - NetworkTopCountriesTableDispatchProps; +type NetworkTopCountriesTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -197,8 +179,12 @@ const makeMapStateToProps = () => { getTopCountriesSelector(state, type, flowTargeted); }; -export const NetworkTopCountriesTable = compose>( - connect(makeMapStateToProps, { - updateNetworkTable: networkActions.updateNetworkTable, - }) -)(NetworkTopCountriesTableComponent); +const mapDispatchToProps = { + updateNetworkTable: networkActions.updateNetworkTable, +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const NetworkTopCountriesTable = connector(NetworkTopCountriesTableComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.tsx index 7c1fcb2681a8c..c4f6dad0a47ed 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.tsx @@ -5,9 +5,7 @@ */ import { isEqual, last } from 'lodash/fp'; import React, { useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { networkActions } from '../../../../store/actions'; import { @@ -36,23 +34,7 @@ interface OwnProps { type: networkModel.NetworkType; } -interface NetworkTopNFlowTableReduxProps { - activePage: number; - limit: number; - sort: NetworkTopTablesSortField; -} - -interface NetworkTopNFlowTableDispatchProps { - updateNetworkTable: ActionCreator<{ - networkType: networkModel.NetworkType; - tableType: networkModel.TopNTableType; - updates: networkModel.TableUpdates; - }>; -} - -type NetworkTopNFlowTableProps = OwnProps & - NetworkTopNFlowTableReduxProps & - NetworkTopNFlowTableDispatchProps; +type NetworkTopNFlowTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -180,8 +162,12 @@ const makeMapStateToProps = () => { getTopNFlowSelector(state, type, flowTargeted); }; -export const NetworkTopNFlowTable = compose>( - connect(makeMapStateToProps, { - updateNetworkTable: networkActions.updateNetworkTable, - }) -)(React.memo(NetworkTopNFlowTableComponent)); +const mapDispatchToProps = { + updateNetworkTable: networkActions.updateNetworkTable, +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const NetworkTopNFlowTable = connector(React.memo(NetworkTopNFlowTableComponent)); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx index 95c0fff054440..77abae68b76bf 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/tls_table/index.tsx @@ -6,9 +6,7 @@ import { isEqual } from 'lodash/fp'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { networkActions } from '../../../../store/network'; import { TlsEdges, TlsSortField, TlsFields, Direction } from '../../../../graphql/types'; @@ -29,21 +27,7 @@ interface OwnProps { type: networkModel.NetworkType; } -interface TlsTableReduxProps { - activePage: number; - limit: number; - sort: TlsSortField; -} - -interface TlsTableDispatchProps { - updateNetworkTable: ActionCreator<{ - networkType: networkModel.NetworkType; - tableType: networkModel.AllNetworkTables; - updates: networkModel.TableUpdates; - }>; -} - -type TlsTableProps = OwnProps & TlsTableReduxProps & TlsTableDispatchProps; +type TlsTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -152,11 +136,15 @@ const makeMapStateToProps = () => { return (state: State, { type }: OwnProps) => getTlsSelector(state, type); }; -export const TlsTable = compose>( - connect(makeMapStateToProps, { - updateNetworkTable: networkActions.updateNetworkTable, - }) -)(TlsTableComponent); +const mapDispatchToProps = { + updateNetworkTable: networkActions.updateNetworkTable, +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const TlsTable = connector(TlsTableComponent); const getSortField = (sortField: TlsSortField): SortingBasicTable => ({ field: `node.${sortField.field}`, diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/users_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/users_table/index.tsx index f4f14c7c009dc..bc7ef2314add4 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/users_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/users_table/index.tsx @@ -6,8 +6,7 @@ import { isEqual } from 'lodash/fp'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { networkActions } from '../../../../store/network'; import { @@ -38,21 +37,7 @@ interface OwnProps { type: networkModel.NetworkType; } -interface UsersTableReduxProps { - activePage: number; - limit: number; - sort: UsersSortField; -} - -interface UsersTableDispatchProps { - updateNetworkTable: ActionCreator<{ - networkType: networkModel.NetworkType; - tableType: networkModel.AllNetworkTables; - updates: networkModel.TableUpdates; - }>; -} - -type UsersTableProps = OwnProps & UsersTableReduxProps & UsersTableDispatchProps; +type UsersTableProps = OwnProps & PropsFromRedux; const rowItems: ItemsPerRow[] = [ { @@ -159,9 +144,15 @@ const makeMapStateToProps = () => { }); }; -export const UsersTable = connect(makeMapStateToProps, { +const mapDispatchToProps = { updateNetworkTable: networkActions.updateNetworkTable, -})(UsersTableComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const UsersTable = connector(UsersTableComponent); const getSortField = (sortField: UsersSortField): SortingBasicTable => { switch (sortField.field) { diff --git a/x-pack/legacy/plugins/siem/public/components/recent_timelines/index.tsx b/x-pack/legacy/plugins/siem/public/components/recent_timelines/index.tsx index d5157e81b0fc8..41eb137742963 100644 --- a/x-pack/legacy/plugins/siem/public/components/recent_timelines/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/recent_timelines/index.tsx @@ -7,14 +7,14 @@ import ApolloClient from 'apollo-client'; import { EuiHorizontalRule, EuiLink, EuiText } from '@elastic/eui'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { ActionCreator } from 'typescript-fsa'; import { AllTimelinesQuery } from '../../containers/timeline/all'; import { SortFieldTimeline, Direction } from '../../graphql/types'; import { queryTimelineById, dispatchUpdateTimeline } from '../open_timeline/helpers'; -import { DispatchUpdateTimeline, OnOpenTimeline } from '../open_timeline/types'; +import { OnOpenTimeline } from '../open_timeline/types'; import { LoadingPlaceholders } from '../page/overview/loading_placeholders'; import { updateIsLoading as dispatchUpdateIsLoading } from '../../store/timeline/actions'; @@ -31,12 +31,7 @@ interface OwnProps { filterBy: FilterMode; } -interface DispatchProps { - updateIsLoading: ({ id, isLoading }: { id: string; isLoading: boolean }) => void; - updateTimeline: DispatchUpdateTimeline; -} - -export type Props = OwnProps & DispatchProps; +export type Props = OwnProps & PropsFromRedux; const StatefulRecentTimelinesComponent = React.memo( ({ apolloClient, filterBy, updateIsLoading, updateTimeline }) => { @@ -100,7 +95,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateTimeline: dispatchUpdateTimeline(dispatch), }); -export const StatefulRecentTimelines = connect( - null, - mapDispatchToProps -)(StatefulRecentTimelinesComponent); +const connector = connect(null, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulRecentTimelines = connector(StatefulRecentTimelinesComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx index 2c3f677cc585d..cb5729ad8e26e 100644 --- a/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/search_bar/index.tsx @@ -6,7 +6,7 @@ import { getOr, isEqual, set } from 'lodash/fp'; import React, { memo, useEffect, useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { Subscription } from 'rxjs'; import styled from 'styled-components'; @@ -34,29 +34,6 @@ import { import { timelineActions, hostsActions, networkActions } from '../../store/actions'; import { useKibana } from '../../lib/kibana'; -interface SiemSearchBarRedux { - end: number; - fromStr: string; - isLoading: boolean; - queries: inputsModel.GlobalGraphqlQuery[]; - filterQuery: Query; - savedQuery?: SavedQuery; - start: number; - toStr: string; -} - -interface SiemSearchBarDispatch { - updateSearch: DispatchUpdateSearch; - setSavedQuery: ({ - id, - savedQuery, - }: { - id: InputsModelId; - savedQuery: SavedQuery | undefined; - }) => void; - setSearchBarFilter: ({ id, filters }: { id: InputsModelId; filters: Filter[] }) => void; -} - interface SiemSearchBarProps { id: InputsModelId; indexPattern: IIndexPattern; @@ -70,7 +47,7 @@ const SearchBarContainer = styled.div` } `; -const SearchBarComponent = memo( +const SearchBarComponent = memo( ({ end, filterQuery, @@ -322,15 +299,7 @@ interface UpdateReduxSearchBar extends OnTimeChangeProps { updateTime: boolean; } -type DispatchUpdateSearch = ({ - end, - id, - isQuickSelection, - start, - timelineId, -}: UpdateReduxSearchBar) => void; - -const dispatchUpdateSearch = (dispatch: Dispatch) => ({ +export const dispatchUpdateSearch = (dispatch: Dispatch) => ({ end, filters, id, @@ -403,4 +372,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ dispatch(inputsActions.setSearchBarFilter({ id, filters })), }); -export const SiemSearchBar = connect(makeMapStateToProps, mapDispatchToProps)(SearchBarComponent); +export const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const SiemSearchBar = connector(SearchBarComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx b/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx index 0877906c721ce..ad38a7d61bcba 100644 --- a/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/super_date_picker/index.tsx @@ -14,7 +14,7 @@ import { } from '@elastic/eui'; import { getOr, take, isEmpty } from 'lodash/fp'; import React, { useState, useCallback } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { DEFAULT_TIMEPICKER_QUICK_RANGES } from '../../../common/constants'; @@ -34,7 +34,7 @@ import { queriesSelector, kqlQuerySelector, } from './selectors'; -import { InputsRange, Policy } from '../../store/inputs/model'; +import { InputsRange } from '../../store/inputs/model'; const MAX_RECENTLY_USED_RANGES = 9; @@ -44,19 +44,6 @@ interface Range { display: string; } -interface SuperDatePickerStateRedux { - duration: number; - end: number; - fromStr: string; - isLoading: boolean; - kind: string; - kqlQuery: inputsModel.GlobalKqlQuery; - policy: Policy['kind']; - queries: inputsModel.GlobalGraphqlQuery[]; - start: number; - toStr: string; -} - interface UpdateReduxTime extends OnTimeChangeProps { id: InputsModelId; kql?: inputsModel.GlobalKqlQuery | undefined; @@ -76,22 +63,13 @@ export type DispatchUpdateReduxTime = ({ timelineId, }: UpdateReduxTime) => ReturnUpdateReduxTime; -interface SuperDatePickerDispatchProps { - setDuration: ({ id, duration }: { id: InputsModelId; duration: number }) => void; - startAutoReload: ({ id }: { id: InputsModelId }) => void; - stopAutoReload: ({ id }: { id: InputsModelId }) => void; - updateReduxTime: DispatchUpdateReduxTime; -} - interface OwnProps { disabled?: boolean; id: InputsModelId; timelineId?: string; } -export type SuperDatePickerProps = OwnProps & - SuperDatePickerDispatchProps & - SuperDatePickerStateRedux; +export type SuperDatePickerProps = OwnProps & PropsFromRedux; export const SuperDatePickerComponent = React.memo( ({ @@ -308,9 +286,9 @@ export const makeMapStateToProps = () => { fromStr: getFromStrSelector(inputsRange), isLoading: getIsLoadingSelector(inputsRange), kind: getKindSelector(inputsRange), - kqlQuery: getKqlQuerySelector(inputsRange), + kqlQuery: getKqlQuerySelector(inputsRange) as inputsModel.GlobalKqlQuery, policy: getPolicySelector(inputsRange), - queries: getQueriesSelector(inputsRange), + queries: getQueriesSelector(inputsRange) as inputsModel.GlobalGraphqlQuery[], start: getStartSelector(inputsRange), toStr: getToStrSelector(inputsRange), }; @@ -328,7 +306,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateReduxTime: dispatchUpdateReduxTime(dispatch), }); -export const SuperDatePicker = connect( - makeMapStateToProps, - mapDispatchToProps -)(SuperDatePickerComponent); +export const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const SuperDatePicker = connector(SuperDatePickerComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/auto_save_warning/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/auto_save_warning/index.tsx index c2dfda6a81ce4..90d0738aba72f 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/auto_save_warning/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/auto_save_warning/index.tsx @@ -12,41 +12,17 @@ import { } from '@elastic/eui'; import { getOr } from 'lodash/fp'; import React from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { State, timelineSelectors } from '../../../store'; import { setTimelineRangeDatePicker as dispatchSetTimelineRangeDatePicker } from '../../../store/inputs/actions'; -import { TimelineModel } from '../../../store/timeline/model'; import * as i18n from './translations'; import { timelineActions } from '../../../store/timeline'; import { AutoSavedWarningMsg } from '../../../store/timeline/types'; import { useStateToaster } from '../../toasters'; -interface ReduxProps { - timelineId: string | null; - newTimelineModel: TimelineModel | null; -} - -interface DispatchProps { - setTimelineRangeDatePicker: ActionCreator<{ - from: number; - to: number; - }>; - updateAutoSaveMsg: ActionCreator<{ - timelineId: string | null; - newTimelineModel: TimelineModel | null; - }>; - updateTimeline: ActionCreator<{ - id: string; - timeline: TimelineModel; - }>; -} - -type OwnProps = ReduxProps & DispatchProps; - -const AutoSaveWarningMsgComponent = React.memo( +const AutoSaveWarningMsgComponent = React.memo( ({ newTimelineModel, setTimelineRangeDatePicker, @@ -106,8 +82,14 @@ const mapStateToProps = (state: State) => { }; }; -export const AutoSaveWarningMsg = connect(mapStateToProps, { +const mapDispatchToProps = { setTimelineRangeDatePicker: dispatchSetTimelineRangeDatePicker, updateAutoSaveMsg: timelineActions.updateAutoSaveMsg, updateTimeline: timelineActions.updateTimeline, -})(AutoSaveWarningMsgComponent); +}; + +const connector = connect(mapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const AutoSaveWarningMsg = connector(AutoSaveWarningMsgComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx index 239d8a9d77916..cf35c8e565bbc 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.test.tsx @@ -66,7 +66,6 @@ describe('Body', () => { onUnPinEvent={jest.fn()} onUpdateColumns={jest.fn()} pinnedEventIds={{}} - range={'1 Day'} rowRenderers={rowRenderers} selectedEventIds={{}} sort={mockSort} @@ -110,7 +109,6 @@ describe('Body', () => { onUnPinEvent={jest.fn()} onUpdateColumns={jest.fn()} pinnedEventIds={{}} - range={'1 Day'} rowRenderers={rowRenderers} selectedEventIds={{}} sort={mockSort} @@ -154,7 +152,6 @@ describe('Body', () => { onUnPinEvent={jest.fn()} onUpdateColumns={jest.fn()} pinnedEventIds={{}} - range={'1 Day'} rowRenderers={rowRenderers} selectedEventIds={{}} sort={mockSort} @@ -200,7 +197,6 @@ describe('Body', () => { onUnPinEvent={jest.fn()} onUpdateColumns={jest.fn()} pinnedEventIds={{}} - range={'1 Day'} rowRenderers={rowRenderers} selectedEventIds={{}} sort={mockSort} @@ -293,7 +289,6 @@ describe('Body', () => { onUnPinEvent={jest.fn()} onUpdateColumns={jest.fn()} pinnedEventIds={{}} - range={'1 Day'} rowRenderers={rowRenderers} selectedEventIds={{}} sort={mockSort} @@ -339,7 +334,6 @@ describe('Body', () => { onUnPinEvent={jest.fn()} onUpdateColumns={jest.fn()} pinnedEventIds={{}} - range={'1 Day'} rowRenderers={rowRenderers} selectedEventIds={{}} sort={mockSort} diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.tsx index f00da48266927..7f689a877c6b7 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/index.tsx @@ -54,7 +54,6 @@ export interface BodyProps { onUpdateColumns: OnUpdateColumns; onUnPinEvent: OnUnPinEvent; pinnedEventIds: Readonly>; - range: string; rowRenderers: RowRenderer[]; selectedEventIds: Readonly>; showCheckboxes: boolean; diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/body/stateful_body.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/body/stateful_body.tsx index edf0613ac2693..ffb5f2a206f4d 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/body/stateful_body.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/body/stateful_body.tsx @@ -7,13 +7,12 @@ import { noop } from 'lodash/fp'; import memoizeOne from 'memoize-one'; import React, { useCallback, useEffect } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { BrowserFields } from '../../../containers/source'; -import { TimelineItem, TimelineNonEcsData } from '../../../graphql/types'; +import { TimelineItem } from '../../../graphql/types'; import { Note } from '../../../lib/note'; -import { appModel, appSelectors, State, timelineSelectors } from '../../../store'; +import { appSelectors, State, timelineSelectors } from '../../../store'; import { AddNoteToEvent, UpdateNote } from '../../notes/helpers'; import { OnColumnRemoved, @@ -46,59 +45,7 @@ interface OwnProps { toggleColumn: (column: ColumnHeader) => void; } -interface ReduxProps { - columnHeaders: ColumnHeader[]; - eventIdToNoteIds: Readonly>; - isSelectAllChecked: boolean; - loadingEventIds: Readonly; - notesById: appModel.NotesById; - pinnedEventIds: Readonly>; - range?: string; - selectedEventIds: Readonly>; - showCheckboxes: boolean; - showRowRenderers: boolean; -} - -interface DispatchProps { - addNoteToEvent?: ActionCreator<{ id: string; noteId: string; eventId: string }>; - applyDeltaToColumnWidth?: ActionCreator<{ - id: string; - columnId: string; - delta: number; - }>; - clearSelected?: ActionCreator<{ - id: string; - }>; - pinEvent?: ActionCreator<{ - id: string; - eventId: string; - }>; - removeColumn?: ActionCreator<{ - id: string; - columnId: string; - }>; - setSelected?: ActionCreator<{ - id: string; - eventIds: Record; - isSelected: boolean; - isSelectAllChecked: boolean; - }>; - unPinEvent?: ActionCreator<{ - id: string; - eventId: string; - }>; - updateColumns?: ActionCreator<{ - id: string; - columns: ColumnHeader[]; - }>; - updateSort?: ActionCreator<{ - id: string; - sort: Sort; - }>; - updateNote?: ActionCreator<{ note: Note }>; -} - -type StatefulBodyComponentProps = OwnProps & ReduxProps & DispatchProps; +type StatefulBodyComponentProps = OwnProps & PropsFromRedux; export const emptyColumnHeaders: ColumnHeader[] = []; @@ -118,7 +65,6 @@ const StatefulBodyComponent = React.memo( notesById, pinEvent, pinnedEventIds, - range, removeColumn, selectedEventIds, setSelected, @@ -234,7 +180,6 @@ const StatefulBodyComponent = React.memo( onUnPinEvent={onUnPinEvent} onUpdateColumns={onUpdateColumns} pinnedEventIds={pinnedEventIds} - range={range!} rowRenderers={showRowRenderers ? rowRenderers : [plainRowRenderer]} selectedEventIds={selectedEventIds} showCheckboxes={showCheckboxes} @@ -260,7 +205,6 @@ const StatefulBodyComponent = React.memo( prevProps.selectedEventIds === nextProps.selectedEventIds && prevProps.showCheckboxes === nextProps.showCheckboxes && prevProps.showRowRenderers === nextProps.showRowRenderers && - prevProps.range === nextProps.range && prevProps.sort === nextProps.sort ); } @@ -307,7 +251,7 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const StatefulBody = connect(makeMapStateToProps, { +const mapDispatchToProps = { addNoteToEvent: timelineActions.addNoteToEvent, applyDeltaToColumnWidth: timelineActions.applyDeltaToColumnWidth, clearSelected: timelineActions.clearSelected, @@ -319,4 +263,10 @@ export const StatefulBody = connect(makeMapStateToProps, { updateColumns: timelineActions.updateColumns, updateNote: appActions.updateNote, updateSort: timelineActions.updateSort, -})(StatefulBodyComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulBody = connector(StatefulBodyComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/fetch_kql_timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/fetch_kql_timeline.tsx index 4b1e723f1bb3a..65c539d77a16b 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/fetch_kql_timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/fetch_kql_timeline.tsx @@ -5,37 +5,21 @@ */ import { memo, useEffect } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { IIndexPattern } from 'src/plugins/data/public'; -import { inputsModel, KueryFilterQuery, timelineSelectors, State } from '../../store'; +import { timelineSelectors, State } from '../../store'; import { inputsActions } from '../../store/actions'; import { InputsModelId } from '../../store/inputs/constants'; import { useUpdateKql } from '../../utils/kql/use_update_kql'; -interface TimelineKqlFetchRedux { - kueryFilterQuery: KueryFilterQuery | null; - kueryFilterQueryDraft: KueryFilterQuery | null; -} - -interface TimelineKqlFetchDispatch { - setTimelineQuery: ActionCreator<{ - id: string; - inputId: InputsModelId; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch | inputsModel.RefetchKql | null; - }>; -} - export interface TimelineKqlFetchProps { id: string; indexPattern: IIndexPattern; inputId: InputsModelId; } -type OwnProps = TimelineKqlFetchProps & TimelineKqlFetchRedux & TimelineKqlFetchDispatch; +type OwnProps = TimelineKqlFetchProps & PropsFromRedux; const TimelineKqlFetchComponent = memo( ({ id, indexPattern, inputId, kueryFilterQuery, kueryFilterQueryDraft, setTimelineQuery }) => { @@ -70,6 +54,12 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const TimelineKqlFetch = connect(makeMapStateToProps, { +const mapDispatchToProps = { setTimelineQuery: inputsActions.setQuery, -})(TimelineKqlFetchComponent); +}; + +export const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const TimelineKqlFetch = connector(TimelineKqlFetchComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx index b6a57ebacb11c..34f760e411ed4 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/index.tsx @@ -6,21 +6,16 @@ import { isEqual } from 'lodash/fp'; import React, { useEffect, useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; - -import { Filter } from '../../../../../../../src/plugins/data/public'; +import { connect, ConnectedProps } from 'react-redux'; import { WithSource } from '../../containers/source'; import { inputsModel, inputsSelectors, State, timelineSelectors } from '../../store'; import { timelineActions } from '../../store/actions'; -import { EventType, KqlMode, timelineDefaults, TimelineModel } from '../../store/timeline/model'; +import { timelineDefaults, TimelineModel } from '../../store/timeline/model'; import { useSignalIndex } from '../../containers/detection_engine/signals/use_signal_index'; import { ColumnHeader } from './body/column_headers/column_header'; -import { DataProvider, QueryOperator } from './data_providers/data_provider'; import { defaultHeaders } from './body/column_headers/default_headers'; -import { Sort } from './body/sort'; import { OnChangeDataProviderKqlQuery, OnChangeDroppableAndProvider, @@ -38,103 +33,7 @@ export interface OwnProps { flyoutHeight: number; } -interface StateReduxProps { - activePage?: number; - columns: ColumnHeader[]; - dataProviders?: DataProvider[]; - eventType: EventType; - end: number; - filters: Filter[]; - isLive: boolean; - itemsPerPage?: number; - itemsPerPageOptions?: number[]; - kqlMode: KqlMode; - kqlQueryExpression: string; - pageCount?: number; - sort?: Sort; - start: number; - show?: boolean; - showCallOutUnauthorizedMsg: boolean; -} - -interface DispatchProps { - createTimeline?: ActionCreator<{ - id: string; - columns: ColumnHeader[]; - show?: boolean; - }>; - addProvider?: ActionCreator<{ - id: string; - provider: DataProvider; - }>; - onDataProviderEdited?: ActionCreator<{ - andProviderId?: string; - excluded: boolean; - field: string; - id: string; - operator: QueryOperator; - providerId: string; - value: string | number; - }>; - updateColumns?: ActionCreator<{ - id: string; - category: string; - columns: ColumnHeader[]; - }>; - updateProviders?: ActionCreator<{ - id: string; - providers: DataProvider[]; - }>; - removeColumn?: ActionCreator<{ - id: string; - columnId: string; - }>; - removeProvider?: ActionCreator<{ - id: string; - providerId: string; - andProviderId?: string; - }>; - updateDataProviderEnabled?: ActionCreator<{ - id: string; - providerId: string; - enabled: boolean; - andProviderId?: string; - }>; - updateDataProviderExcluded?: ActionCreator<{ - id: string; - excluded: boolean; - providerId: string; - andProviderId?: string; - }>; - updateDataProviderKqlQuery?: ActionCreator<{ - id: string; - kqlQuery: string; - providerId: string; - }>; - updateItemsPerPage?: ActionCreator<{ - id: string; - itemsPerPage: number; - }>; - updateItemsPerPageOptions?: ActionCreator<{ - id: string; - itemsPerPageOptions: number[]; - }>; - updatePageIndex?: ActionCreator<{ - id: string; - activePage: number; - }>; - updateHighlightedDropAndProviderId?: ActionCreator<{ - id: string; - providerId: string; - }>; - upsertColumn?: ActionCreator<{ - column: ColumnHeader; - id: string; - index: number; - }>; -} - -type Props = OwnProps & StateReduxProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; const StatefulTimelineComponent = React.memo( ({ @@ -169,7 +68,12 @@ const StatefulTimelineComponent = React.memo( const { loading, signalIndexExists, signalIndexName } = useSignalIndex(); const indexToAdd = useMemo(() => { - if (signalIndexExists && signalIndexName != null && ['signal', 'all'].includes(eventType)) { + if ( + eventType && + signalIndexExists && + signalIndexName != null && + ['signal', 'all'].includes(eventType) + ) { return [signalIndexName]; } return []; @@ -300,7 +204,6 @@ const StatefulTimelineComponent = React.memo( }, (prevProps, nextProps) => { return ( - prevProps.activePage === nextProps.activePage && prevProps.eventType === nextProps.eventType && prevProps.end === nextProps.end && prevProps.flyoutHeaderHeight === nextProps.flyoutHeaderHeight && @@ -310,7 +213,6 @@ const StatefulTimelineComponent = React.memo( prevProps.itemsPerPage === nextProps.itemsPerPage && prevProps.kqlMode === nextProps.kqlMode && prevProps.kqlQueryExpression === nextProps.kqlQueryExpression && - prevProps.pageCount === nextProps.pageCount && prevProps.show === nextProps.show && prevProps.showCallOutUnauthorizedMsg === nextProps.showCallOutUnauthorizedMsg && prevProps.start === nextProps.start && @@ -344,7 +246,7 @@ const makeMapStateToProps = () => { show, sort, } = timeline; - const kqlQueryExpression = getKqlQueryTimeline(state, id); + const kqlQueryExpression = getKqlQueryTimeline(state, id)!; const timelineFilter = kqlMode === 'filter' ? filters || [] : []; @@ -369,7 +271,7 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const StatefulTimeline = connect(makeMapStateToProps, { +const mapDispatchToProps = { addProvider: timelineActions.addProvider, createTimeline: timelineActions.createTimeline, onDataProviderEdited: timelineActions.dataProviderEdited, @@ -384,4 +286,10 @@ export const StatefulTimeline = connect(makeMapStateToProps, { updateItemsPerPageOptions: timelineActions.updateItemsPerPageOptions, updateSort: timelineActions.updateSort, upsertColumn: timelineActions.upsertColumn, -})(StatefulTimelineComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulTimeline = connector(StatefulTimelineComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/refetch_timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/refetch_timeline.tsx index c804ccf658296..3d2ec0683f091 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/refetch_timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/refetch_timeline.tsx @@ -5,33 +5,21 @@ */ import React, { useEffect } from 'react'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { inputsModel } from '../../store'; import { inputsActions } from '../../store/actions'; import { InputsModelId } from '../../store/inputs/constants'; -interface TimelineRefetchDispatch { - setTimelineQuery: ActionCreator<{ - id: string; - inputId: InputsModelId; - inspect: inputsModel.InspectQuery | null; - loading: boolean; - refetch: inputsModel.Refetch | inputsModel.RefetchKql | null; - }>; -} - export interface TimelineRefetchProps { id: string; inputId: InputsModelId; inspect: inputsModel.InspectQuery | null; loading: boolean; - refetch: inputsModel.Refetch | null; + refetch: inputsModel.Refetch; } -type OwnProps = TimelineRefetchProps & TimelineRefetchDispatch; +type OwnProps = TimelineRefetchProps & PropsFromRedux; const TimelineRefetchComponent: React.FC = ({ id, @@ -48,8 +36,12 @@ const TimelineRefetchComponent: React.FC = ({ return null; }; -export const TimelineRefetch = compose>( - connect(null, { - setTimelineQuery: inputsActions.setQuery, - }) -)(React.memo(TimelineRefetchComponent)); +const mapDispatchToProps = { + setTimelineQuery: inputsActions.setQuery, +}; + +const connector = connect(null, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const TimelineRefetch = connector(React.memo(TimelineRefetchComponent)); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx index 3c47823fbbc3b..2b139d3948fe1 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/search_or_filter/index.tsx @@ -6,7 +6,7 @@ import { getOr, isEqual } from 'lodash/fp'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; import { Filter, IIndexPattern } from '../../../../../../../../src/plugins/data/public'; @@ -22,8 +22,7 @@ import { } from '../../../store'; import { timelineActions } from '../../../store/actions'; import { KqlMode, timelineDefaults, TimelineModel, EventType } from '../../../store/timeline/model'; -import { DispatchUpdateReduxTime, dispatchUpdateReduxTime } from '../../super_date_picker'; -import { DataProvider } from '../data_providers/data_provider'; +import { dispatchUpdateReduxTime } from '../../super_date_picker'; import { SearchOrFilter } from './search_or_filter'; interface OwnProps { @@ -32,45 +31,7 @@ interface OwnProps { timelineId: string; } -interface StateReduxProps { - dataProviders: DataProvider[]; - eventType: EventType; - filters: Filter[]; - filterQuery: KueryFilterQuery; - filterQueryDraft: KueryFilterQuery; - from: number; - fromStr: string; - isRefreshPaused: boolean; - kqlMode: KqlMode; - refreshInterval: number; - savedQueryId: string | null; - to: number; - toStr: string; -} - -interface DispatchProps { - applyKqlFilterQuery: ({ - id, - filterQuery, - }: { - id: string; - filterQuery: SerializedFilterQuery; - }) => void; - updateEventType: ({ id, eventType }: { id: string; eventType: EventType }) => void; - updateKqlMode: ({ id, kqlMode }: { id: string; kqlMode: KqlMode }) => void; - setKqlFilterQueryDraft: ({ - id, - filterQueryDraft, - }: { - id: string; - filterQueryDraft: KueryFilterQuery; - }) => void; - setSavedQueryId: ({ id, savedQueryId }: { id: string; savedQueryId: string | null }) => void; - setFilters: ({ id, filters }: { id: string; filters: Filter[] }) => void; - updateReduxTime: DispatchUpdateReduxTime; -} - -type Props = OwnProps & StateReduxProps & DispatchProps; +type Props = OwnProps & PropsFromRedux; const StatefulSearchOrFilterComponent = React.memo( ({ @@ -217,17 +178,17 @@ const makeMapStateToProps = () => { return { dataProviders: timeline.dataProviders, eventType: timeline.eventType ?? 'raw', - filterQuery: getKqlFilterQuery(state, timelineId), - filterQueryDraft: getKqlFilterQueryDraft(state, timelineId), - filters: timeline.filters, + filterQuery: getKqlFilterQuery(state, timelineId)!, + filterQueryDraft: getKqlFilterQueryDraft(state, timelineId)!, + filters: timeline.filters!, from: input.timerange.from, - fromStr: input.timerange.fromStr, + fromStr: input.timerange.fromStr!, isRefreshPaused: policy.kind === 'manual', kqlMode: getOr('filter', 'kqlMode', timeline), refreshInterval: policy.duration, savedQueryId: getOr(null, 'savedQueryId', timeline), to: input.timerange.to, - toStr: input.timerange.toStr, + toStr: input.timerange.toStr!, }; }; return mapStateToProps; @@ -265,7 +226,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateReduxTime: dispatchUpdateReduxTime(dispatch), }); -export const StatefulSearchOrFilter = connect( - makeMapStateToProps, - mapDispatchToProps -)(StatefulSearchOrFilterComponent); +export const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulSearchOrFilter = connector(StatefulSearchOrFilterComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx index 9d70b69124f30..09457c8f0285a 100644 --- a/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx +++ b/x-pack/legacy/plugins/siem/public/components/timeline/timeline.tsx @@ -60,7 +60,7 @@ interface Props { columns: ColumnHeader[]; dataProviders: DataProvider[]; end: number; - eventType: EventType; + eventType?: EventType; filters: Filter[]; flyoutHeaderHeight: number; flyoutHeight: number; diff --git a/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx b/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx index d77e0215f8353..caf597d02c835 100644 --- a/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/global_time/index.tsx @@ -5,12 +5,10 @@ */ import React, { useState, useEffect } from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; +import { connect, ConnectedProps } from 'react-redux'; import { inputsModel, inputsSelectors, State } from '../../store'; import { inputsActions } from '../../store/actions'; -import { InputsModelId } from '../../store/inputs/constants'; interface SetQuery { id: string; @@ -19,10 +17,6 @@ interface SetQuery { refetch: inputsModel.Refetch | inputsModel.RefetchKql; } -interface GlobalQuery extends SetQuery { - inputId: InputsModelId; -} - export interface GlobalTimeArgs { from: number; to: number; @@ -31,21 +25,11 @@ export interface GlobalTimeArgs { isInitializing: boolean; } -interface GlobalTimeDispatch { - setGlobalQuery: ActionCreator; - deleteAllQuery: ActionCreator<{ id: InputsModelId }>; - deleteOneQuery: ActionCreator<{ inputId: InputsModelId; id: string }>; -} - -interface GlobalTimeReduxState { - from: number; - to: number; -} interface OwnProps { children: (args: GlobalTimeArgs) => React.ReactNode; } -type GlobalTimeProps = OwnProps & GlobalTimeReduxState & GlobalTimeDispatch; +type GlobalTimeProps = OwnProps & PropsFromRedux; export const GlobalTimeComponent: React.FC = ({ children, @@ -88,8 +72,14 @@ const mapStateToProps = (state: State) => { }; }; -export const GlobalTime = connect(mapStateToProps, { +const mapDispatchToProps = { deleteAllQuery: inputsActions.deleteAllQuery, deleteOneQuery: inputsActions.deleteOneQuery, setGlobalQuery: inputsActions.setQuery, -})(React.memo(GlobalTimeComponent)); +}; + +export const connector = connect(mapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const GlobalTime = connector(React.memo(GlobalTimeComponent)); diff --git a/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.tsx b/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.tsx index 9576c66c4c9a5..ade94c430c6ef 100644 --- a/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/ip_overview/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { GetIpOverviewQuery, IpOverviewData } from '../../graphql/types'; @@ -28,17 +28,13 @@ export interface IpOverviewArgs { refetch: inputsModel.Refetch; } -export interface IpOverviewReduxProps { - isInspected: boolean; -} - export interface IpOverviewProps extends QueryTemplateProps { children: (args: IpOverviewArgs) => React.ReactNode; type: networkModel.NetworkType; ip: string; } -const IpOverviewComponentQuery = React.memo( +const IpOverviewComponentQuery = React.memo( ({ id = ID, isInspected, children, filterQuery, skip, sourceId, ip }) => ( query={ipOverviewQuery} @@ -81,4 +77,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const IpOverviewQuery = connect(makeMapStateToProps)(IpOverviewComponentQuery); +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const IpOverviewQuery = connector(IpOverviewComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.tsx b/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.tsx index 501bc8472b5e2..de9d54b1a185c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/kpi_host_details/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { KpiHostDetailsData, GetKpiHostDetailsQuery } from '../../graphql/types'; @@ -32,11 +32,7 @@ export interface QueryKpiHostDetailsProps extends QueryTemplateProps { children: (args: KpiHostDetailsArgs) => React.ReactNode; } -export interface KpiHostDetailsReducer { - isInspected: boolean; -} - -const KpiHostDetailsComponentQuery = React.memo( +const KpiHostDetailsComponentQuery = React.memo( ({ id = ID, children, endDate, filterQuery, isInspected, skip, sourceId, startDate }) => ( query={kpiHostDetailsQuery} @@ -82,4 +78,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const KpiHostDetailsQuery = connect(makeMapStateToProps)(KpiHostDetailsComponentQuery); +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const KpiHostDetailsQuery = connector(KpiHostDetailsComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.tsx b/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.tsx index 32472ba6deedf..5be2423e8a162 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/kpi_hosts/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { GetKpiHostsQuery, KpiHostsData } from '../../graphql/types'; @@ -28,15 +28,11 @@ export interface KpiHostsArgs { refetch: inputsModel.Refetch; } -export interface KpiHostsReducer { - isInspected: boolean; -} - export interface KpiHostsProps extends QueryTemplateProps { children: (args: KpiHostsArgs) => React.ReactNode; } -const KpiHostsComponentQuery = React.memo( +const KpiHostsComponentQuery = React.memo( ({ id = ID, children, endDate, filterQuery, isInspected, skip, sourceId, startDate }) => ( query={kpiHostsQuery} @@ -82,4 +78,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const KpiHostsQuery = connect(makeMapStateToProps)(KpiHostsComponentQuery); +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const KpiHostsQuery = connector(KpiHostsComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.tsx b/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.tsx index 52b8814958ba0..338cdc39b178c 100644 --- a/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/kpi_network/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { GetKpiNetworkQuery, KpiNetworkData } from '../../graphql/types'; @@ -28,15 +28,11 @@ export interface KpiNetworkArgs { refetch: inputsModel.Refetch; } -export interface KpiNetworkReducer { - isInspected: boolean; -} - export interface KpiNetworkProps extends QueryTemplateProps { children: (args: KpiNetworkArgs) => React.ReactNode; } -const KpiNetworkComponentQuery = React.memo( +const KpiNetworkComponentQuery = React.memo( ({ id = ID, children, filterQuery, isInspected, skip, sourceId, startDate, endDate }) => ( query={kpiNetworkQuery} @@ -82,4 +78,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const KpiNetworkQuery = connect(makeMapStateToProps)(KpiNetworkComponentQuery); +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const KpiNetworkQuery = connector(KpiNetworkComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.tsx b/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.tsx index 8c40c4044a746..2dd9ccf24d802 100644 --- a/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/overview/overview_host/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { GetOverviewHostQuery, OverviewHostData } from '../../../graphql/types'; @@ -29,10 +29,6 @@ export interface OverviewHostArgs { refetch: inputsModel.Refetch; } -export interface OverviewHostReducer { - isInspected: boolean; -} - export interface OverviewHostProps extends QueryTemplateProps { children: (args: OverviewHostArgs) => React.ReactNode; sourceId: string; @@ -40,7 +36,7 @@ export interface OverviewHostProps extends QueryTemplateProps { startDate: number; } -const OverviewHostComponentQuery = React.memo( +const OverviewHostComponentQuery = React.memo( ({ id = ID, children, filterQuery, isInspected, sourceId, startDate, endDate }) => { return ( @@ -86,4 +82,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const OverviewHostQuery = connect(makeMapStateToProps)(OverviewHostComponentQuery); +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const OverviewHostQuery = connector(OverviewHostComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.tsx b/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.tsx index 9e7d59de0e546..d0acd41c224a5 100644 --- a/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/overview/overview_network/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { GetOverviewNetworkQuery, OverviewNetworkData } from '../../../graphql/types'; @@ -29,10 +29,6 @@ export interface OverviewNetworkArgs { refetch: inputsModel.Refetch; } -export interface OverviewNetworkReducer { - isInspected: boolean; -} - export interface OverviewNetworkProps extends QueryTemplateProps { children: (args: OverviewNetworkArgs) => React.ReactNode; sourceId: string; @@ -40,37 +36,37 @@ export interface OverviewNetworkProps extends QueryTemplateProps { startDate: number; } -export const OverviewNetworkComponentQuery = React.memo< - OverviewNetworkProps & OverviewNetworkReducer ->(({ id = ID, children, filterQuery, isInspected, sourceId, startDate, endDate }) => ( - - query={overviewNetworkQuery} - fetchPolicy={getDefaultFetchPolicy()} - notifyOnNetworkStatusChange - variables={{ - sourceId, - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - filterQuery: createFilter(filterQuery), - defaultIndex: useUiSetting(DEFAULT_INDEX_KEY), - inspect: isInspected, - }} - > - {({ data, loading, refetch }) => { - const overviewNetwork = getOr({}, `source.OverviewNetwork`, data); - return children({ - id, - inspect: getOr(null, 'source.OverviewNetwork.inspect', data), - overviewNetwork, - loading, - refetch, - }); - }} - -)); +export const OverviewNetworkComponentQuery = React.memo( + ({ id = ID, children, filterQuery, isInspected, sourceId, startDate, endDate }) => ( + + query={overviewNetworkQuery} + fetchPolicy={getDefaultFetchPolicy()} + notifyOnNetworkStatusChange + variables={{ + sourceId, + timerange: { + interval: '12h', + from: startDate, + to: endDate, + }, + filterQuery: createFilter(filterQuery), + defaultIndex: useUiSetting(DEFAULT_INDEX_KEY), + inspect: isInspected, + }} + > + {({ data, loading, refetch }) => { + const overviewNetwork = getOr({}, `source.OverviewNetwork`, data); + return children({ + id, + inspect: getOr(null, 'source.OverviewNetwork.inspect', data), + overviewNetwork, + loading, + refetch, + }); + }} + + ) +); OverviewNetworkComponentQuery.displayName = 'OverviewNetworkComponentQuery'; @@ -85,4 +81,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const OverviewNetworkQuery = connect(makeMapStateToProps)(OverviewNetworkComponentQuery); +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + +export const OverviewNetworkQuery = connector(OverviewNetworkComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx b/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx index f4eb088b6ad94..68d87ef565fb7 100644 --- a/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/timeline/index.tsx @@ -9,7 +9,7 @@ import memoizeOne from 'memoize-one'; import React from 'react'; import { Query } from 'react-apollo'; import { compose } from 'redux'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { IIndexPattern } from '../../../../../../../src/plugins/data/common/index_patterns'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; @@ -39,10 +39,6 @@ export interface TimelineArgs { getUpdatedAt: () => number; } -export interface TimelineQueryReduxProps { - isInspected: boolean; -} - export interface OwnProps extends QueryTemplateProps { children?: (args: TimelineArgs) => React.ReactNode; eventType?: EventType; @@ -53,7 +49,8 @@ export interface OwnProps extends QueryTemplateProps { sortField: SortField; fields: string[]; } -type TimelineQueryProps = OwnProps & TimelineQueryReduxProps & WithKibanaProps; + +type TimelineQueryProps = OwnProps & PropsFromRedux & WithKibanaProps; class TimelineQueryComponent extends QueryTemplate< TimelineQueryProps, @@ -171,7 +168,11 @@ const makeMapStateToProps = () => { return mapStateToProps; }; +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + export const TimelineQuery = compose>( - connect(makeMapStateToProps), + connector, withKibana )(TimelineQueryComponent); diff --git a/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.tsx b/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.tsx index 520ade954eb5c..0a2ce67d9be80 100644 --- a/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/uncommon_processes/index.tsx @@ -7,7 +7,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { compose } from 'redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; @@ -43,13 +43,7 @@ export interface OwnProps extends QueryTemplatePaginatedProps { type: hostsModel.HostsType; } -export interface UncommonProcessesComponentReduxProps { - activePage: number; - isInspected: boolean; - limit: number; -} - -type UncommonProcessesProps = OwnProps & UncommonProcessesComponentReduxProps & WithKibanaProps; +type UncommonProcessesProps = OwnProps & PropsFromRedux & WithKibanaProps; class UncommonProcessesComponentQuery extends QueryTemplatePaginated< UncommonProcessesProps, @@ -144,7 +138,11 @@ const makeMapStateToProps = () => { return mapStateToProps; }; +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + export const UncommonProcessesQuery = compose>( - connect(makeMapStateToProps), + connector, withKibana )(UncommonProcessesComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/users/index.tsx b/x-pack/legacy/plugins/siem/public/containers/users/index.tsx index ece73b7b10ff0..5f71449c52460 100644 --- a/x-pack/legacy/plugins/siem/public/containers/users/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/users/index.tsx @@ -7,17 +7,11 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { compose } from 'redux'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; -import { - GetUsersQuery, - FlowTarget, - PageInfoPaginated, - UsersEdges, - UsersSortField, -} from '../../graphql/types'; +import { GetUsersQuery, FlowTarget, PageInfoPaginated, UsersEdges } from '../../graphql/types'; import { inputsModel, networkModel, networkSelectors, State, inputsSelectors } from '../../store'; import { withKibana, WithKibanaProps } from '../../lib/kibana'; import { createFilter, getDefaultFetchPolicy } from '../helpers'; @@ -47,14 +41,7 @@ export interface OwnProps extends QueryTemplatePaginatedProps { type: networkModel.NetworkType; } -export interface UsersComponentReduxProps { - activePage: number; - isInspected: boolean; - limit: number; - sort: UsersSortField; -} - -type UsersProps = OwnProps & UsersComponentReduxProps & WithKibanaProps; +type UsersProps = OwnProps & PropsFromRedux & WithKibanaProps; class UsersComponentQuery extends QueryTemplatePaginated< UsersProps, @@ -156,7 +143,11 @@ const makeMapStateToProps = () => { return mapStateToProps; }; +const connector = connect(makeMapStateToProps); + +type PropsFromRedux = ConnectedProps; + export const UsersQuery = compose>( - connect(makeMapStateToProps), + connector, withKibana )(UsersComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx index 8108e24cfa2c3..aacc6d951f4c9 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/index.tsx @@ -7,17 +7,14 @@ import { EuiPanel, EuiLoadingContent } from '@elastic/eui'; import { isEmpty } from 'lodash/fp'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; -import { ActionCreator } from 'typescript-fsa'; -import { Filter, esQuery, Query } from '../../../../../../../../../src/plugins/data/public'; +import { Filter, esQuery } from '../../../../../../../../../src/plugins/data/public'; import { useFetchIndexPatterns } from '../../../../containers/detection_engine/rules/fetch_index_patterns'; import { StatefulEventsViewer } from '../../../../components/events_viewer'; import { HeaderSection } from '../../../../components/header_section'; -import { DispatchUpdateTimeline } from '../../../../components/open_timeline/types'; import { combineQueries } from '../../../../components/timeline/helpers'; -import { TimelineNonEcsData } from '../../../../graphql/types'; import { useKibana } from '../../../../lib/kibana'; import { inputsSelectors, State, inputsModel } from '../../../../store'; import { timelineActions, timelineSelectors } from '../../../../store/timeline'; @@ -51,33 +48,6 @@ import { dispatchUpdateTimeline } from '../../../../components/open_timeline/hel const SIGNALS_PAGE_TIMELINE_ID = 'signals-page'; -interface ReduxProps { - globalQuery: Query; - globalFilters: Filter[]; - deletedEventIds: string[]; - isSelectAllChecked: boolean; - loadingEventIds: string[]; - selectedEventIds: Readonly>; -} - -interface DispatchProps { - clearEventsDeleted?: ActionCreator<{ id: string }>; - clearEventsLoading?: ActionCreator<{ id: string }>; - clearSelected?: ActionCreator<{ id: string }>; - setEventsDeleted?: ActionCreator<{ - id: string; - eventIds: string[]; - isDeleted: boolean; - }>; - setEventsLoading?: ActionCreator<{ - id: string; - eventIds: string[]; - isLoading: boolean; - }>; - updateTimelineIsLoading: ActionCreator<{ id: string; isLoading: boolean }>; - updateTimeline: DispatchUpdateTimeline; -} - interface OwnProps { canUserCRUD: boolean; defaultFilters?: Filter[]; @@ -88,7 +58,7 @@ interface OwnProps { to: number; } -type SignalsTableComponentProps = OwnProps & ReduxProps & DispatchProps; +type SignalsTableComponentProps = OwnProps & PropsFromRedux; const SignalsTableComponent: React.FC = ({ canUserCRUD, @@ -390,7 +360,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ updateTimeline: dispatchUpdateTimeline(dispatch), }); -export const SignalsTable = connect( - makeMapStateToProps, - mapDispatchToProps -)(React.memo(SignalsTableComponent)); +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const SignalsTable = connector(React.memo(SignalsTableComponent)); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx index 8cfcac8fc862b..c3fb907ae83e1 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx @@ -8,11 +8,7 @@ import { EuiButton, EuiSpacer } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import { useParams } from 'react-router-dom'; import { StickyContainer } from 'react-sticky'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; - -import { Query } from '../../../../../../../src/plugins/data/common/query'; -import { Filter } from '../../../../../../../src/plugins/data/common/es_query'; +import { connect, ConnectedProps } from 'react-redux'; import { GlobalTime } from '../../containers/global_time'; import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; @@ -30,7 +26,6 @@ import { State } from '../../store'; import { inputsSelectors } from '../../store/inputs'; import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from '../../store/inputs/actions'; import { SpyRoute } from '../../utils/route/spy_routes'; -import { InputsModelId } from '../../store/inputs/constants'; import { InputsRange } from '../../store/inputs/model'; import { AlertsByCategory } from '../overview/alerts_by_category'; import { useSignalInfo } from './components/signals_info'; @@ -47,21 +42,6 @@ import { DetectionEngineUserUnauthenticated } from './detection_engine_user_unau import * as i18n from './translations'; import { DetectionEngineTab } from './types'; -interface ReduxProps { - filters: Filter[]; - query: Query; -} - -export interface DispatchProps { - setAbsoluteRangeDatePicker: ActionCreator<{ - id: InputsModelId; - from: number; - to: number; - }>; -} - -type DetectionEnginePageComponentProps = ReduxProps & DispatchProps; - const detectionsTabs: Record = { [DetectionEngineTab.signals]: { id: DetectionEngineTab.signals, @@ -79,7 +59,7 @@ const detectionsTabs: Record = { }, }; -const DetectionEnginePageComponent: React.FC = ({ +const DetectionEnginePageComponent: React.FC = ({ filters, query, setAbsoluteRangeDatePicker, @@ -234,7 +214,8 @@ const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, }; -export const DetectionEnginePage = connect( - makeMapStateToProps, - mapDispatchToProps -)(React.memo(DetectionEnginePageComponent)); +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const DetectionEnginePage = connector(React.memo(DetectionEnginePageComponent)); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx index dc1ebd6052538..83dd18f0f14b7 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx @@ -19,9 +19,8 @@ import { FormattedMessage } from '@kbn/i18n/react'; import React, { FC, memo, useCallback, useMemo, useState } from 'react'; import { Redirect, useParams } from 'react-router-dom'; import { StickyContainer } from 'react-sticky'; +import { connect, ConnectedProps } from 'react-redux'; -import { ActionCreator } from 'typescript-fsa'; -import { connect } from 'react-redux'; import { FiltersGlobal } from '../../../../components/filters_global'; import { FormattedDate } from '../../../../components/formatted_date'; import { @@ -59,9 +58,6 @@ import * as ruleI18n from '../translations'; import * as i18n from './translations'; import { GlobalTime } from '../../../../containers/global_time'; import { signalsHistogramOptions } from '../../components/signals_histogram_panel/config'; -import { InputsModelId } from '../../../../store/inputs/constants'; -import { Filter } from '../../../../../../../../../src/plugins/data/common/es_query'; -import { Query } from '../../../../../../../../../src/plugins/data/common/query'; import { inputsSelectors } from '../../../../store/inputs'; import { State } from '../../../../store'; import { InputsRange } from '../../../../store/inputs/model'; @@ -71,19 +67,6 @@ import { RuleStatusFailedCallOut } from './status_failed_callout'; import { FailureHistory } from './failure_history'; import { RuleStatus } from '../components/rule_status'; -interface ReduxProps { - filters: Filter[]; - query: Query; -} - -export interface DispatchProps { - setAbsoluteRangeDatePicker: ActionCreator<{ - id: InputsModelId; - from: number; - to: number; - }>; -} - enum RuleDetailTabs { signals = 'signals', failures = 'failures', @@ -102,9 +85,7 @@ const ruleDetailTabs = [ }, ]; -type RuleDetailsComponentProps = ReduxProps & DispatchProps; - -const RuleDetailsPageComponent: FC = ({ +const RuleDetailsPageComponent: FC = ({ filters, query, setAbsoluteRangeDatePicker, @@ -417,7 +398,8 @@ const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, }; -export const RuleDetailsPage = connect( - makeMapStateToProps, - mapDispatchToProps -)(memo(RuleDetailsPageComponent)); +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const RuleDetailsPage = connector(memo(RuleDetailsPageComponent)); diff --git a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx index 9ee103f88793d..1dce26b7c5d3a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/home/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/home/index.tsx @@ -104,9 +104,7 @@ export const HomePage: React.FC = () => ( /> ( - - )} + render={({ match }) => } /> ( +export const HostDetailsTabs = React.memo( ({ pageFilters, deleteQuery, @@ -105,5 +105,3 @@ const HostDetailsTabs = React.memo( ); HostDetailsTabs.displayName = 'HostDetailsTabs'; - -export { HostDetailsTabs }; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx index a02e2b4aed22e..8af4731e4dda4 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/details/index.tsx @@ -6,9 +6,8 @@ import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; import React, { useContext, useEffect, useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { StickyContainer } from 'react-sticky'; -import { compose } from 'redux'; import { FiltersGlobal } from '../../../components/filters_global'; import { HeaderPage } from '../../../components/header_page'; @@ -39,14 +38,14 @@ import { esQuery, Filter } from '../../../../../../../../src/plugins/data/public import { HostsEmptyPage } from '../hosts_empty_page'; import { HostDetailsTabs } from './details_tabs'; import { navTabsHostDetails } from './nav_tabs'; -import { HostDetailsComponentProps, HostDetailsProps } from './types'; +import { HostDetailsProps } from './types'; import { type } from './utils'; import { getHostDetailsPageFilters } from './helpers'; const HostOverviewManage = manageQuery(HostOverview); const KpiHostDetailsManage = manageQuery(KpiHostsComponent); -const HostDetailsComponent = React.memo( +const HostDetailsComponent = React.memo( ({ filters, from, @@ -61,7 +60,7 @@ const HostDetailsComponent = React.memo( hostDetailsPagePath, }) => { useEffect(() => { - setHostDetailsTablesActivePageToZero(null); + setHostDetailsTablesActivePageToZero(); }, [setHostDetailsTablesActivePageToZero, detailName]); const capabilities = useContext(MlCapabilitiesContext); const kibana = useKibana(); @@ -218,9 +217,13 @@ export const makeMapStateToProps = () => { }); }; -export const HostDetails = compose>( - connect(makeMapStateToProps, { - setAbsoluteRangeDatePicker: dispatchAbsoluteRangeDatePicker, - setHostDetailsTablesActivePageToZero: dispatchHostDetailsTablesActivePageToZero, - }) -)(HostDetailsComponent); +const mapDispatchToProps = { + setAbsoluteRangeDatePicker: dispatchAbsoluteRangeDatePicker, + setHostDetailsTablesActivePageToZero: dispatchHostDetailsTablesActivePageToZero, +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const HostDetails = connector(HostDetailsComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx index 71dc3aac756ba..99cf767c65e08 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.test.tsx @@ -9,14 +9,12 @@ import { cloneDeep } from 'lodash/fp'; import React from 'react'; import { Router } from 'react-router-dom'; import { MockedProvider } from 'react-apollo/test-utils'; -import { ActionCreator } from 'typescript-fsa'; import { Filter } from '../../../../../../../src/plugins/data/common/es_query'; import '../../mock/match_media'; import { mocksSource } from '../../containers/source/mock'; import { wait } from '../../lib/helpers'; import { apolloClientObservable, TestProviders, mockGlobalState } from '../../mock'; -import { InputsModelId } from '../../store/inputs/constants'; import { SiemNavigation } from '../../components/navigation'; import { inputsActions } from '../../store/inputs'; import { State, createStore } from '../../store'; @@ -77,13 +75,6 @@ describe('Hosts - rendering', () => { to, setQuery: jest.fn(), isInitializing: false, - setAbsoluteRangeDatePicker: (jest.fn() as unknown) as ActionCreator<{ - from: number; - id: InputsModelId; - to: number; - }>, - query: { query: '', language: 'kuery' }, - filters: [], hostsPagePath: '', }; diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx index 06dffcdb220a9..a7aa9920b7d08 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/hosts.tsx @@ -6,9 +6,8 @@ import { EuiSpacer } from '@elastic/eui'; import React, { useCallback } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { StickyContainer } from 'react-sticky'; -import { compose } from 'redux'; import { useParams } from 'react-router-dom'; import { FiltersGlobal } from '../../components/filters_global'; @@ -21,7 +20,6 @@ import { KpiHostsComponent } from '../../components/page/hosts'; import { manageQuery } from '../../components/page/manage_query'; import { SiemSearchBar } from '../../components/search_bar'; import { WrapperPage } from '../../components/wrapper_page'; -import { GlobalTimeArgs } from '../../containers/global_time'; import { KpiHostsQuery } from '../../containers/kpi_hosts'; import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; import { LastEventIndexKey } from '../../graphql/types'; @@ -36,13 +34,13 @@ import { HostsEmptyPage } from './hosts_empty_page'; import { HostsTabs } from './hosts_tabs'; import { navTabsHosts } from './nav_tabs'; import * as i18n from './translations'; -import { HostsComponentProps, HostsComponentReduxProps } from './types'; +import { HostsComponentProps } from './types'; import { filterHostData } from './navigation'; import { HostsTableType } from '../../store/hosts/model'; const KpiHostsComponentManage = manageQuery(KpiHostsComponent); -export const HostsComponent = React.memo( +export const HostsComponent = React.memo( ({ deleteQuery, isInitializing, @@ -161,7 +159,7 @@ HostsComponent.displayName = 'HostsComponent'; const makeMapStateToProps = () => { const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); - const mapStateToProps = (state: State): HostsComponentReduxProps => ({ + const mapStateToProps = (state: State) => ({ query: getGlobalQuerySelector(state), filters: getGlobalFiltersQuerySelector(state), }); @@ -169,13 +167,12 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -interface HostsProps extends GlobalTimeArgs { - hostsPagePath: string; -} +const mapDispatchToProps = { + setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const Hosts = compose>( - connect(makeMapStateToProps, { - setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, - }) -)(HostsComponent); +export const Hosts = connector(HostsComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx index fff5c5218c003..699b1441905c3 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/index.tsx @@ -56,10 +56,14 @@ export const HostsContainer = React.memo(({ url }) => ( ( + render={({ + match: { + params: { detailName }, + }, + }) => ( ; - hostsPagePath: string; -} - -export type HostsTabsProps = HostsComponentDispatchProps & - HostsQueryProps & { - filterQuery: string; - type: hostsModel.HostsType; - indexPattern: IIndexPattern; - }; +}; export type HostsQueryProps = GlobalTimeArgs; -export type HostsComponentProps = HostsComponentReduxProps & - HostsComponentDispatchProps & - HostsQueryProps; +export type HostsComponentProps = HostsQueryProps & { hostsPagePath: string }; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx index 9a9d1cf085eb9..02132d790796c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.test.tsx @@ -92,7 +92,7 @@ const getMockProps = (ip: string) => ({ from: number; to: number; }>, - setIpDetailsTablesActivePageToZero: (jest.fn() as unknown) as ActionCreator, + setIpDetailsTablesActivePageToZero: (jest.fn() as unknown) as ActionCreator, }); describe('Ip Details', () => { diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx index 2e8044d2c2fe8..e796eaca0cd28 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/index.tsx @@ -6,7 +6,7 @@ import { EuiHorizontalRule, EuiSpacer, EuiFlexItem } from '@elastic/eui'; import React, { useCallback, useEffect } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { StickyContainer } from 'react-sticky'; import { FiltersGlobal } from '../../../components/filters_global'; @@ -46,7 +46,7 @@ export { getBreadcrumbs } from './utils'; const IpOverviewManage = manageQuery(IpOverview); -export const IPDetailsComponent = ({ +export const IPDetailsComponent: React.FC = ({ detailName, filters, flowTarget, @@ -57,7 +57,7 @@ export const IPDetailsComponent = ({ setIpDetailsTablesActivePageToZero, setQuery, to, -}: IPDetailsComponentProps) => { +}) => { const type = networkModel.NetworkType.details; const narrowDateRange = useCallback( (score, interval) => { @@ -73,7 +73,7 @@ export const IPDetailsComponent = ({ const kibana = useKibana(); useEffect(() => { - setIpDetailsTablesActivePageToZero(null); + setIpDetailsTablesActivePageToZero(); }, [detailName, setIpDetailsTablesActivePageToZero]); return ( @@ -279,13 +279,20 @@ IPDetailsComponent.displayName = 'IPDetailsComponent'; const makeMapStateToProps = () => { const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); + return (state: State) => ({ query: getGlobalQuerySelector(state), filters: getGlobalFiltersQuerySelector(state), }); }; -export const IPDetails = connect(makeMapStateToProps, { +const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchAbsoluteRangeDatePicker, setIpDetailsTablesActivePageToZero: dispatchIpDetailsTablesActivePageToZero, -})(React.memo(IPDetailsComponent)); +}; + +export const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const IPDetails = connector(React.memo(IPDetailsComponent)); diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/types.ts b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/types.ts index b53d58e6664af..ef989fb64eabe 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details/types.ts @@ -4,38 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ActionCreator } from 'typescript-fsa'; -import { IIndexPattern, Query, Filter } from 'src/plugins/data/public'; +import { IIndexPattern } from 'src/plugins/data/public'; import { NetworkType } from '../../../store/network/model'; import { ESTermQuery } from '../../../../common/typed_json'; import { InspectQuery, Refetch } from '../../../store/inputs/model'; import { FlowTarget, FlowTargetSourceDest } from '../../../graphql/types'; -import { InputsModelId } from '../../../store/inputs/constants'; import { GlobalTimeArgs } from '../../../containers/global_time'; export const type = NetworkType.details; -type SetAbsoluteRangeDatePicker = ActionCreator<{ - id: InputsModelId; - from: number; - to: number; -}>; - -interface IPDetailsComponentReduxProps { - filters: Filter[]; +export type IPDetailsComponentProps = GlobalTimeArgs & { + detailName: string; flowTarget: FlowTarget; - query: Query; -} - -interface IPDetailsComponentDispatchProps { - setAbsoluteRangeDatePicker: SetAbsoluteRangeDatePicker; - setIpDetailsTablesActivePageToZero: ActionCreator; -} - -export type IPDetailsComponentProps = IPDetailsComponentReduxProps & - IPDetailsComponentDispatchProps & - GlobalTimeArgs & { detailName: string }; +}; export interface OwnProps { type: NetworkType; diff --git a/x-pack/legacy/plugins/siem/public/pages/network/network.tsx b/x-pack/legacy/plugins/siem/public/pages/network/network.tsx index 0f9eaaef48aa7..9b1ee76e1d376 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/network.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/network.tsx @@ -6,7 +6,7 @@ import { EuiSpacer } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { useParams } from 'react-router-dom'; import { StickyContainer } from 'react-sticky'; @@ -38,7 +38,7 @@ import { NetworkRouteType } from './navigation/types'; const KpiNetworkComponentManage = manageQuery(KpiNetworkComponent); const sourceId = 'default'; -const NetworkComponent = React.memo( +const NetworkComponent = React.memo( ({ filters, query, @@ -183,6 +183,12 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export const Network = connect(makeMapStateToProps, { +const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker, -})(NetworkComponent); +}; + +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const Network = connector(NetworkComponent); diff --git a/x-pack/legacy/plugins/siem/public/pages/network/types.ts b/x-pack/legacy/plugins/siem/public/pages/network/types.ts index 8a9914133c9af..01d3fb6b48c63 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/network/types.ts @@ -6,9 +6,8 @@ import { RouteComponentProps } from 'react-router-dom'; import { ActionCreator } from 'typescript-fsa'; -import { GlobalTimeArgs } from '../../containers/global_time'; import { InputsModelId } from '../../store/inputs/constants'; -import { Query, Filter } from '../../../../../../../src/plugins/data/public'; +import { GlobalTimeArgs } from '../../containers/global_time'; export type SetAbsoluteRangeDatePicker = ActionCreator<{ id: InputsModelId; @@ -16,15 +15,8 @@ export type SetAbsoluteRangeDatePicker = ActionCreator<{ to: number; }>; -interface NetworkComponentReduxProps { - filters: Filter[]; - query: Query; - setAbsoluteRangeDatePicker: SetAbsoluteRangeDatePicker; -} - -export type NetworkComponentProps = NetworkComponentReduxProps & - GlobalTimeArgs & - Partial> & { +export type NetworkComponentProps = Partial> & + GlobalTimeArgs & { networkPagePath: string; hasMlUserPermissions: boolean; capabilitiesFetched: boolean; diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx index 8505b91fe1ff5..2db49e60193fc 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/overview.tsx @@ -6,9 +6,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import React from 'react'; -import { connect } from 'react-redux'; +import { connect, ConnectedProps } from 'react-redux'; import { StickyContainer } from 'react-sticky'; -import { compose } from 'redux'; import { Query, Filter } from 'src/plugins/data/public'; import styled from 'styled-components'; @@ -20,7 +19,6 @@ import { GlobalTime } from '../../containers/global_time'; import { WithSource, indicesExistOrDataTemporarilyUnavailable } from '../../containers/source'; import { EventsByDataset } from './events_by_dataset'; import { EventCounts } from './event_counts'; -import { SetAbsoluteRangeDatePicker } from '../network/types'; import { OverviewEmpty } from './overview_empty'; import { StatefulSidebar } from './sidebar'; import { SignalsByCategory } from './signals_by_category'; @@ -35,13 +33,7 @@ const SidebarFlexItem = styled(EuiFlexItem)` margin-right: 24px; `; -interface OverviewComponentReduxProps { - query?: Query; - filters?: Filter[]; - setAbsoluteRangeDatePicker?: SetAbsoluteRangeDatePicker; -} - -const OverviewComponent: React.FC = ({ +const OverviewComponent: React.FC = ({ filters = NO_FILTERS, query = DEFAULT_QUERY, setAbsoluteRangeDatePicker, @@ -133,7 +125,7 @@ const makeMapStateToProps = () => { const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); - const mapStateToProps = (state: State): OverviewComponentReduxProps => ({ + const mapStateToProps = (state: State) => ({ query: getGlobalQuerySelector(state), filters: getGlobalFiltersQuerySelector(state), }); @@ -143,6 +135,8 @@ const makeMapStateToProps = () => { const mapDispatchToProps = { setAbsoluteRangeDatePicker: dispatchSetAbsoluteRangeDatePicker }; -export const StatefulOverview = compose>( - connect(makeMapStateToProps, mapDispatchToProps) -)(React.memo(OverviewComponent)); +const connector = connect(makeMapStateToProps, mapDispatchToProps); + +type PropsFromRedux = ConnectedProps; + +export const StatefulOverview = connector(React.memo(OverviewComponent)); diff --git a/x-pack/legacy/plugins/siem/public/store/inputs/actions.ts b/x-pack/legacy/plugins/siem/public/store/inputs/actions.ts index 8255ba41d2bb1..f9da0e558c655 100644 --- a/x-pack/legacy/plugins/siem/public/store/inputs/actions.ts +++ b/x-pack/legacy/plugins/siem/public/store/inputs/actions.ts @@ -7,7 +7,7 @@ import actionCreatorFactory from 'typescript-fsa'; import { SavedQuery } from 'src/legacy/core_plugins/data/public'; -import { InspectQuery, Refetch } from './model'; +import { InspectQuery, Refetch, RefetchKql } from './model'; import { InputsModelId } from './constants'; import { Filter } from '../../../../../../../src/plugins/data/public'; @@ -42,7 +42,7 @@ export const setQuery = actionCreator<{ inputId: InputsModelId; id: string; loading: boolean; - refetch: Refetch; + refetch: Refetch | RefetchKql; inspect: InspectQuery | null; }>('SET_QUERY'); diff --git a/x-pack/legacy/plugins/siem/public/store/inputs/helpers.ts b/x-pack/legacy/plugins/siem/public/store/inputs/helpers.ts index 194d2e8cd35c3..4a3c17a6234e7 100644 --- a/x-pack/legacy/plugins/siem/public/store/inputs/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/store/inputs/helpers.ts @@ -6,7 +6,7 @@ import { get } from 'lodash/fp'; -import { InputsModel, TimeRange, Refetch, InspectQuery } from './model'; +import { InputsModel, TimeRange, Refetch, RefetchKql, InspectQuery } from './model'; import { InputsModelId } from './constants'; export const updateInputTimerange = ( @@ -59,7 +59,7 @@ export interface UpdateQueryParams { inputId: InputsModelId; inspect: InspectQuery | null; loading: boolean; - refetch: Refetch; + refetch: Refetch | RefetchKql; state: InputsModel; } diff --git a/x-pack/legacy/plugins/siem/public/store/network/selectors.ts b/x-pack/legacy/plugins/siem/public/store/network/selectors.ts index 64a325b6e1ca4..273eaf7c0ee7f 100644 --- a/x-pack/legacy/plugins/siem/public/store/network/selectors.ts +++ b/x-pack/legacy/plugins/siem/public/store/network/selectors.ts @@ -16,6 +16,9 @@ import { NetworkPageModel, NetworkTableType, NetworkType, + TopCountriesQuery, + TlsQuery, + HttpQuery, } from './model'; const selectNetworkPage = (state: State): NetworkPageModel => state.network.page; @@ -41,7 +44,7 @@ const selectTopNFlowByType = ( export const topNFlowSelector = () => createSelector(selectTopNFlowByType, topNFlowQueries => topNFlowQueries); -const selectTlsByType = (state: State, networkType: NetworkType) => { +const selectTlsByType = (state: State, networkType: NetworkType): TlsQuery => { const tlsType = networkType === NetworkType.page ? NetworkTableType.tls : IpDetailsTableType.tls; return ( get([networkType, 'queries', tlsType], state.network) || @@ -55,7 +58,7 @@ const selectTopCountriesByType = ( state: State, networkType: NetworkType, flowTarget: FlowTargetSourceDest -) => { +): TopCountriesQuery => { const ft = flowTarget === FlowTargetSourceDest.source ? 'topCountriesSource' : 'topCountriesDestination'; const nFlowType = @@ -70,7 +73,7 @@ const selectTopCountriesByType = ( export const topCountriesSelector = () => createSelector(selectTopCountriesByType, topCountriesQueries => topCountriesQueries); -const selectHttpByType = (state: State, networkType: NetworkType) => { +const selectHttpByType = (state: State, networkType: NetworkType): HttpQuery => { const httpType = networkType === NetworkType.page ? NetworkTableType.http : IpDetailsTableType.http; return ( diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx index 744c82a9983c8..b4989282f854c 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx @@ -31,7 +31,7 @@ export interface PingHistogramComponentProps { */ height?: string; - data?: HistogramResult; + data: HistogramResult | null; loading?: boolean; } diff --git a/x-pack/legacy/plugins/uptime/public/contexts/uptime_refresh_context.tsx b/x-pack/legacy/plugins/uptime/public/contexts/uptime_refresh_context.tsx index 4516289bd51d6..8e406f621f648 100644 --- a/x-pack/legacy/plugins/uptime/public/contexts/uptime_refresh_context.tsx +++ b/x-pack/legacy/plugins/uptime/public/contexts/uptime_refresh_context.tsx @@ -28,6 +28,7 @@ export const UptimeRefreshContextProvider: React.FC = ({ children }) => { const refreshApp = () => { const refreshTime = Date.now(); setLastRefresh(refreshTime); + // @ts-ignore store.dispatch(triggerAppRefresh(refreshTime)); }; diff --git a/x-pack/legacy/plugins/uptime/public/uptime_app.tsx b/x-pack/legacy/plugins/uptime/public/uptime_app.tsx index db34566d6c148..66ff5ba7a58ee 100644 --- a/x-pack/legacy/plugins/uptime/public/uptime_app.tsx +++ b/x-pack/legacy/plugins/uptime/public/uptime_app.tsx @@ -85,6 +85,7 @@ const Application = (props: UptimeAppProps) => { ); }, [canSave, renderGlobalHelpControls, setBadge]); + // @ts-ignore store.dispatch(setBasePath(basePath)); return ( diff --git a/x-pack/package.json b/x-pack/package.json index e3bc8aa36373d..37791c255aee9 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -65,7 +65,7 @@ "@types/graphql": "^0.13.2", "@types/gulp": "^4.0.6", "@types/hapi__wreck": "^15.0.1", - "@types/hoist-non-react-statics": "^3.3.0", + "@types/hoist-non-react-statics": "^3.3.1", "@types/history": "^4.7.3", "@types/jest": "24.0.19", "@types/joi": "^13.4.2", @@ -88,14 +88,14 @@ "@types/prop-types": "^15.5.3", "@types/proper-lockfile": "^3.0.1", "@types/puppeteer": "^1.20.1", - "@types/react": "^16.9.11", - "@types/react-dom": "^16.9.4", - "@types/react-redux": "^6.0.6", + "@types/react": "^16.9.19", + "@types/react-dom": "^16.9.5", + "@types/react-redux": "^7.1.7", "@types/react-router-dom": "^5.1.3", "@types/react-sticky": "^6.0.3", "@types/react-test-renderer": "^16.9.1", "@types/recompose": "^0.30.6", - "@types/reduce-reducers": "^0.3.0", + "@types/reduce-reducers": "^1.0.0", "@types/redux-actions": "^2.6.1", "@types/sinon": "^7.0.13", "@types/styled-components": "^4.4.2", @@ -118,10 +118,10 @@ "copy-webpack-plugin": "^5.0.4", "cypress": "^3.6.1", "cypress-multi-reporters": "^1.2.3", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.15.1", - "enzyme-adapter-utils": "^1.12.1", - "enzyme-to-json": "^3.4.3", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.2", + "enzyme-adapter-utils": "^1.13.0", + "enzyme-to-json": "^3.4.4", "execa": "^3.2.0", "fancy-log": "^1.3.2", "fetch-mock": "^7.3.9", @@ -134,6 +134,7 @@ "graphql-codegen-typescript-server": "^0.18.2", "gulp": "4.0.2", "hapi": "^17.5.3", + "hoist-non-react-statics": "^3.3.2", "jest": "^24.9.0", "jest-cli": "^24.9.0", "jest-styled-components": "^7.0.0", @@ -305,7 +306,7 @@ "react-markdown": "^3.4.1", "react-moment-proptypes": "^1.7.0", "react-portal": "^3.2.0", - "react-redux": "^5.1.2", + "react-redux": "^7.1.3", "react-reverse-portal": "^1.0.4", "react-router-dom": "^5.1.2", "react-shortcuts": "^2.0.0", @@ -316,15 +317,15 @@ "react-vis": "^1.8.1", "react-visibility-sensor": "^5.1.1", "recompose": "^0.26.0", - "reduce-reducers": "^0.4.3", - "redux": "4.0.0", - "redux-actions": "2.6.5", - "redux-observable": "^1.0.0", + "reduce-reducers": "^1.0.4", + "redux": "^4.0.5", + "redux-actions": "^2.6.5", + "redux-observable": "^1.2.0", "redux-saga": "^0.16.0", - "redux-thunk": "2.3.0", + "redux-thunk": "^2.3.0", "redux-thunks": "^1.0.0", "request": "^2.88.0", - "reselect": "3.0.1", + "reselect": "^4.0.0", "resize-observer-polyfill": "^1.5.0", "rison-node": "0.3.1", "rxjs": "^6.5.3", @@ -339,8 +340,8 @@ "topojson-client": "3.0.0", "tslib": "^1.9.3", "turf": "3.0.14", - "typescript-fsa": "^2.5.0", - "typescript-fsa-reducers": "^0.4.5", + "typescript-fsa": "^3.0.0", + "typescript-fsa-reducers": "^1.2.1", "ui-select": "0.19.8", "unstated": "^2.1.1", "uuid": "3.3.2", diff --git a/yarn.lock b/yarn.lock index 33cb366e72f00..27967aefa20c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4391,7 +4391,7 @@ resolved "https://registry.yarnpkg.com/@types/elasticsearch/-/elasticsearch-5.0.33.tgz#b0fd37dc674f498223b6d68c313bdfd71f4d812b" integrity sha512-n/g9pqJEpE4fyUE8VvHNGtl7E2Wv8TCroNwfgAeJKRV4ghDENahtrAo1KMsFNIejBD2gDAlEUa4CM4oEEd8p9Q== -"@types/enzyme@^3.1.13", "@types/enzyme@^3.9.0": +"@types/enzyme@^3.1.13", "@types/enzyme@^3.10.5": version "3.10.5" resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.10.5.tgz#fe7eeba3550369eed20e7fb565bfb74eec44f1f0" integrity sha512-R+phe509UuUYy9Tk0YlSbipRpfVtIzb/9BHn5pTEtjJTF5LXvUjrIQcZvNyANNEyFrd2YGs196PniNT1fgvOQA== @@ -4580,7 +4580,7 @@ resolved "https://registry.yarnpkg.com/@types/hoek/-/hoek-4.1.3.tgz#d1982d48fb0d2a0e5d7e9d91838264d8e428d337" integrity sha1-0ZgtSPsNKg5dfp2Rg4Jk2OQo0zc= -"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.0": +"@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.0", "@types/hoist-non-react-statics@^3.3.1": version "3.3.1" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== @@ -4998,13 +4998,20 @@ dependencies: "@types/react" "*" -"@types/react-dom@*", "@types/react-dom@^16.9.4": +"@types/react-dom@*": version "16.9.4" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.4.tgz#0b58df09a60961dcb77f62d4f1832427513420df" integrity sha512-fya9xteU/n90tda0s+FtN5Ym4tbgxpq/hb/Af24dvs6uYnYn+fspaxw5USlw0R8apDNwxsqumdRoCoKitckQqw== dependencies: "@types/react" "*" +"@types/react-dom@^16.9.5": + version "16.9.5" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.5.tgz#5de610b04a35d07ffd8f44edad93a71032d9aaa7" + integrity sha512-BX6RQ8s9D+2/gDhxrj8OW+YD4R+8hj7FEM/OJHGNR0KipE1h1mSsf39YeyC81qafkq+N3rU3h3RFbLSwE5VqUg== + dependencies: + "@types/react" "*" + "@types/react-grid-layout@^0.16.7": version "0.16.7" resolved "https://registry.yarnpkg.com/@types/react-grid-layout/-/react-grid-layout-0.16.7.tgz#53d5f5034deb0c60e25a0fa578141e9a0982011f" @@ -5025,14 +5032,6 @@ "@types/prop-types" "*" "@types/react" "*" -"@types/react-redux@^6.0.6": - version "6.0.6" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-6.0.6.tgz#87f1d0a6ea901b93fcaf95fa57641ff64079d277" - integrity sha512-sD/QEn45h+CH0OAhCn6/9COlihZ94bzpP58QzYYCL3tOFta/WBhuvMoyLP8khJLfwQBx1PT70HP/1GnDws9YXQ== - dependencies: - "@types/react" "*" - redux "^4.0.0" - "@types/react-redux@^7.1.0": version "7.1.5" resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.5.tgz#c7a528d538969250347aa53c52241051cf886bd3" @@ -5043,6 +5042,16 @@ hoist-non-react-statics "^3.3.0" redux "^4.0.0" +"@types/react-redux@^7.1.7": + version "7.1.7" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.7.tgz#12a0c529aba660696947384a059c5c6e08185c7a" + integrity sha512-U+WrzeFfI83+evZE2dkZ/oF/1vjIYgqrb5dGgedkqVV8HEfDFujNgWCwHL89TDuWKb47U0nTBT6PLGq4IIogWg== + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + redux "^4.0.0" + "@types/react-resize-detector@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/react-resize-detector/-/react-resize-detector-4.0.1.tgz#cc8f012f5957e4826e69b8d2afd59baadcac556c" @@ -5103,10 +5112,10 @@ "@types/prop-types" "*" "@types/react" "*" -"@types/react@*", "@types/react@^16.8.23", "@types/react@^16.9.11", "@types/react@^16.9.13": - version "16.9.15" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.15.tgz#aeabb7a50f96c9e31a16079ada20ede9ed602977" - integrity sha512-WsmM1b6xQn1tG3X2Hx4F3bZwc2E82pJXt5OPs2YJgg71IzvUoKOSSSYOvLXYCg1ttipM+UuA4Lj3sfvqjVxyZw== +"@types/react@*", "@types/react@^16.8.23", "@types/react@^16.9.19": + version "16.9.19" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.19.tgz#c842aa83ea490007d29938146ff2e4d9e4360c40" + integrity sha512-LJV97//H+zqKWMms0kvxaKYJDG05U2TtQB3chRLF8MPNs+MQh/H1aGlyDUxjaHvu08EAGerdX2z4LTBc7ns77A== dependencies: "@types/prop-types" "*" csstype "^2.2.0" @@ -5125,23 +5134,18 @@ dependencies: "@types/react" "*" -"@types/reduce-reducers@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@types/reduce-reducers/-/reduce-reducers-0.3.0.tgz#d86d88049c38bebbafa5baf121282d765fabbebf" - integrity sha512-S9Vi74p0UOlqf9dqiurBwNBp+ABAGZ7nJAZteFS6LS8y9u2fkGfvNk1gtauKoDG+BuB4vjp1+P/R0/r5rFxYDQ== +"@types/reduce-reducers@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/reduce-reducers/-/reduce-reducers-1.0.0.tgz#033120b109159f4b344210ee75310d1ec3fcc8ef" + integrity sha512-MWKF9QDH/HaMQZvGyQlrut1ttyrFVIrGZqhCXPBcl5LelhnfC7dIE2jK2qZjxFHUCeXgjKCk5hN+/GzA7GgqjQ== dependencies: - redux "^4.0.0" + reduce-reducers "*" "@types/redux-actions@^2.6.1": version "2.6.1" resolved "https://registry.yarnpkg.com/@types/redux-actions/-/redux-actions-2.6.1.tgz#0940e97fa35ad3004316bddb391d8e01d2efa605" integrity sha512-zKgK+ATp3sswXs6sOYo1tk8xdXTy4CTaeeYrVQlClCjeOpag5vzPo0ASWiiBJ7vsiQRAdb3VkuFLnDoBimF67g== -"@types/redux@^3.6.31": - version "3.6.31" - resolved "https://registry.yarnpkg.com/@types/redux/-/redux-3.6.31.tgz#40eafa7575db36b912ce0059b85de98c205b0708" - integrity sha1-QOr6dXXbNrkSzgBZuF3pjCBbBwg= - "@types/request@^2.48.2": version "2.48.2" resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.2.tgz#936374cbe1179d7ed529fc02543deb4597450fed" @@ -6807,14 +6811,13 @@ array.prototype.find@^2.1.0: define-properties "^1.1.3" es-abstract "^1.13.0" -array.prototype.flat@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz#812db8f02cad24d3fab65dd67eabe3b8903494a4" - integrity sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw== +array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" + integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ== dependencies: - define-properties "^1.1.2" - es-abstract "^1.10.0" - function-bind "^1.1.1" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" array.prototype.flatmap@^1.2.1: version "1.2.1" @@ -8967,7 +8970,7 @@ cheerio@0.22.0: lodash.reject "^4.4.0" lodash.some "^4.4.0" -cheerio@^1.0.0-rc.2: +cheerio@^1.0.0-rc.3: version "1.0.0-rc.3" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.3.tgz#094636d425b2e9c0f4eb91a46c05630c9a1a8bf6" integrity sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA== @@ -12218,74 +12221,76 @@ env-variable@0.0.x: resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.5.tgz#913dd830bef11e96a039c038d4130604eba37f88" integrity sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA== -enzyme-adapter-react-16@^1.15.1: - version "1.15.1" - resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.1.tgz#8ad55332be7091dc53a25d7d38b3485fc2ba50d5" - integrity sha512-yMPxrP3vjJP+4wL/qqfkT6JAIctcwKF+zXO6utlGPgUJT2l4tzrdjMDWGd/Pp1BjHBcljhN24OzNEGRteibJhA== +enzyme-adapter-react-16@^1.15.2: + version "1.15.2" + resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.2.tgz#b16db2f0ea424d58a808f9df86ab6212895a4501" + integrity sha512-SkvDrb8xU3lSxID8Qic9rB8pvevDbLybxPK6D/vW7PrT0s2Cl/zJYuXvsd1EBTz0q4o3iqG3FJhpYz3nUNpM2Q== dependencies: - enzyme-adapter-utils "^1.12.1" - enzyme-shallow-equal "^1.0.0" + enzyme-adapter-utils "^1.13.0" + enzyme-shallow-equal "^1.0.1" has "^1.0.3" object.assign "^4.1.0" - object.values "^1.1.0" + object.values "^1.1.1" prop-types "^15.7.2" - react-is "^16.10.2" + react-is "^16.12.0" react-test-renderer "^16.0.0-0" semver "^5.7.0" -enzyme-adapter-utils@^1.12.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.12.1.tgz#e828e0d038e2b1efa4b9619ce896226f85c9dd88" - integrity sha512-KWiHzSjZaLEoDCOxY8Z1RAbUResbqKN5bZvenPbfKtWorJFVETUw754ebkuCQ3JKm0adx1kF8JaiR+PHPiP47g== +enzyme-adapter-utils@^1.13.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.13.0.tgz#01c885dde2114b4690bf741f8dc94cee3060eb78" + integrity sha512-YuEtfQp76Lj5TG1NvtP2eGJnFKogk/zT70fyYHXK2j3v6CtuHqc8YmgH/vaiBfL8K1SgVVbQXtTcgQZFwzTVyQ== dependencies: airbnb-prop-types "^2.15.0" - function.prototype.name "^1.1.1" + function.prototype.name "^1.1.2" object.assign "^4.1.0" - object.fromentries "^2.0.1" + object.fromentries "^2.0.2" prop-types "^15.7.2" - semver "^5.7.0" + semver "^5.7.1" -enzyme-shallow-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.0.tgz#d8e4603495e6ea279038eef05a4bf4887b55dc69" - integrity sha512-VUf+q5o1EIv2ZaloNQQtWCJM9gpeux6vudGVH6vLmfPXFLRuxl5+Aq3U260wof9nn0b0i+P5OEUXm1vnxkRpXQ== +enzyme-shallow-equal@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.1.tgz#7afe03db3801c9b76de8440694096412a8d9d49e" + integrity sha512-hGA3i1so8OrYOZSM9whlkNmVHOicJpsjgTzC+wn2JMJXhq1oO4kA4bJ5MsfzSIcC71aLDKzJ6gZpIxrqt3QTAQ== dependencies: has "^1.0.3" - object-is "^1.0.1" + object-is "^1.0.2" -enzyme-to-json@^3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.4.3.tgz#ed4386f48768ed29e2d1a2910893542c34e7e0af" - integrity sha512-jqNEZlHqLdz7OTpXSzzghArSS3vigj67IU/fWkPyl1c0TCj9P5s6Ze0kRkYZWNEoCqCR79xlQbigYlMx5erh8A== +enzyme-to-json@^3.4.4: + version "3.4.4" + resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.4.4.tgz#b30726c59091d273521b6568c859e8831e94d00e" + integrity sha512-50LELP/SCPJJGic5rAARvU7pgE3m1YaNj7JLM+Qkhl5t7PAs6fiyc8xzc50RnkKPFQCv0EeFVjEWdIFRGPWMsA== dependencies: lodash "^4.17.15" + react-is "^16.12.0" -enzyme@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.10.0.tgz#7218e347c4a7746e133f8e964aada4a3523452f6" - integrity sha512-p2yy9Y7t/PFbPoTvrWde7JIYB2ZyGC+NgTNbVEGvZ5/EyoYSr9aG/2rSbVvyNvMHEhw9/dmGUJHWtfQIEiX9pg== +enzyme@^3.11.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.11.0.tgz#71d680c580fe9349f6f5ac6c775bc3e6b7a79c28" + integrity sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw== dependencies: - array.prototype.flat "^1.2.1" - cheerio "^1.0.0-rc.2" - function.prototype.name "^1.1.0" + array.prototype.flat "^1.2.3" + cheerio "^1.0.0-rc.3" + enzyme-shallow-equal "^1.0.1" + function.prototype.name "^1.1.2" has "^1.0.3" - html-element-map "^1.0.0" - is-boolean-object "^1.0.0" - is-callable "^1.1.4" - is-number-object "^1.0.3" - is-regex "^1.0.4" - is-string "^1.0.4" + html-element-map "^1.2.0" + is-boolean-object "^1.0.1" + is-callable "^1.1.5" + is-number-object "^1.0.4" + is-regex "^1.0.5" + is-string "^1.0.5" is-subset "^0.1.1" lodash.escape "^4.0.1" lodash.isequal "^4.5.0" - object-inspect "^1.6.0" - object-is "^1.0.1" + object-inspect "^1.7.0" + object-is "^1.0.2" object.assign "^4.1.0" - object.entries "^1.0.4" - object.values "^1.0.4" - raf "^3.4.0" + object.entries "^1.1.1" + object.values "^1.1.1" + raf "^3.4.1" rst-selector-parser "^2.2.3" - string.prototype.trim "^1.1.2" + string.prototype.trim "^1.2.1" errlop@^1.1.2: version "1.1.2" @@ -12335,26 +12340,44 @@ error@^7.0.0, error@^7.0.2: string-template "~0.2.1" xtend "~4.0.0" -es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.13.0, es-abstract@^1.14.2, es-abstract@^1.15.0, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.7.0, es-abstract@^1.9.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" - integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== +es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.13.0, es-abstract@^1.14.2, es-abstract@^1.17.0-next.1, es-abstract@^1.4.3, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.7.0, es-abstract@^1.9.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0.tgz#f42a517d0036a5591dbb2c463591dc8bb50309b1" + integrity sha512-yYkE07YF+6SIBmg1MsJ9dlub5L48Ek7X0qz+c/CPCHS9EBXfESorzng4cJQjJW5/pB6vDF41u7F8vUhLVDqIug== dependencies: - es-to-primitive "^1.2.0" + es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.0" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-inspect "^1.6.0" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" object-keys "^1.1.1" - string.prototype.trimleft "^2.1.0" - string.prototype.trimright "^2.1.0" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" -es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== +es-abstract@^1.15.0: + version "1.17.4" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184" + integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" @@ -14417,31 +14440,21 @@ function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -function.prototype.name@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.0.tgz#8bd763cc0af860a859cc5d49384d74b932cd2327" - integrity sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - is-callable "^1.1.3" - -function.prototype.name@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.1.tgz#6d252350803085abc2ad423d4fe3be2f9cbda392" - integrity sha512-e1NzkiJuw6xqVH7YSdiW/qDHebcmMhPNe6w+4ZYYEg0VA+LaLzx37RimbPLuonHhYGFGPx1ME2nSi74JiaCr/Q== +function.prototype.name@^1.1.0, function.prototype.name@^1.1.1, function.prototype.name@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.2.tgz#5cdf79d7c05db401591dfde83e3b70c5123e9a45" + integrity sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg== dependencies: define-properties "^1.1.3" - function-bind "^1.1.1" - functions-have-names "^1.1.1" - is-callable "^1.1.4" + es-abstract "^1.17.0-next.1" + functions-have-names "^1.2.0" functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -functions-have-names@^1.1.1: +functions-have-names@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.0.tgz#83da7583e4ea0c9ac5ff530f73394b033e0bf77d" integrity sha512-zKXyzksTeaCSw5wIX79iCA40YAa6CJMJgNg9wdkU/ERBrIdPSimPICYiLp65lRbSBqtiHql/HZfS2DyI/AH6tQ== @@ -15876,10 +15889,10 @@ has-symbol-support-x@^1.4.1: resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= +has-symbols@^1.0.0, has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== has-to-string-tag-x@^1.2.0: version "1.4.1" @@ -16110,22 +16123,10 @@ hoek@6.x.x: resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.0.3.tgz#7884360426d927865a0a1251fc9c59313af5b798" integrity sha512-TU6RyZ/XaQCTWRLrdqZZtZqwxUVr6PDMfi6MlWNURZ7A6czanQqX4pFE1mdOUQR9FdPCsZ0UzL8jI/izZ+eBSQ== -hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0, hoist-non-react-statics@^2.5.5: - version "2.5.5" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" - integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== - -hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#101685d3aff3b23ea213163f6e8e12f4f111e19f" - integrity sha512-wbg3bpgA/ZqWrZuMOeJi8+SKMhr7X9TesL/rXMjTzh0p0JUBo3II8DHboYbuIXWRlttrUFxwcu/5kygrCw8fJw== - dependencies: - react-is "^16.7.0" - -hoist-non-react-statics@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" - integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA== +hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0, hoist-non-react-statics@^2.5.5, hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== dependencies: react-is "^16.7.0" @@ -16156,10 +16157,10 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -html-element-map@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.0.1.tgz#3c4fcb4874ebddfe4283b51c8994e7713782b592" - integrity sha512-BZSfdEm6n706/lBfXKWa4frZRZcT5k1cOusw95ijZsHlI+GdgY0v95h6IzO3iIDf2ROwq570YTwqNPqHcNMozw== +html-element-map@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.2.0.tgz#dfbb09efe882806af63d990cf6db37993f099f22" + integrity sha512-0uXq8HsuG1v2TmQ8QkIhzbrqeskE4kn52Q18QJ9iAA/SnHoEKXWiUxHQtclRsCFWEUD2So34X+0+pZZu862nnw== dependencies: array-filter "^1.0.0" @@ -16967,7 +16968,7 @@ invariant@2.2.4, invariant@^2.1.0, invariant@^2.1.1, invariant@^2.2.3, invariant dependencies: loose-envify "^1.0.0" -invariant@^2.0.0, invariant@^2.2.1, invariant@^2.2.2: +invariant@^2.2.1, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" integrity sha1-nh9WrArNtr8wMwbzOL47IErmA2A= @@ -17099,10 +17100,10 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93" - integrity sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M= +is-boolean-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.1.tgz#10edc0900dd127697a92f6f9807c7617d68ac48e" + integrity sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ== is-buffer@^1.0.2, is-buffer@^1.1.4, is-buffer@^1.1.5, is-buffer@~1.1.1: version "1.1.6" @@ -17121,10 +17122,10 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" -is-callable@^1.1.3, is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== is-ci@1.2.1: version "1.2.1" @@ -17374,10 +17375,10 @@ is-npm@^1.0.0: resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= -is-number-object@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.3.tgz#f265ab89a9f445034ef6aff15a8f00b00f551799" - integrity sha1-8mWrian0RQNO9q/xWo8AsA9VF5k= +is-number-object@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" + integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== is-number@^0.1.1: version "0.1.1" @@ -17514,12 +17515,12 @@ is-redirect@^1.0.0: resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= -is-regex@^1.0.3, is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= +is-regex@^1.0.3, is-regex@^1.0.4, is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== dependencies: - has "^1.0.1" + has "^1.0.3" is-regexp@^1.0.0: version "1.0.0" @@ -17587,10 +17588,10 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== -is-string@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.4.tgz#cc3a9b69857d621e963725a24caeec873b826e64" - integrity sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ= +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== is-subset@^0.1.1: version "0.1.1" @@ -17655,12 +17656,7 @@ is-whitespace-character@^1.0.0: resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.1.tgz#9ae0176f3282b65457a1992cdb084f8a5f833e3b" integrity sha1-muAXbzKCtlRXoZks2whPil+DPjs= -is-windows@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9" - integrity sha1-MQ23D3QtJZoWo2kgK1GvhCMzENk= - -is-windows@^1.0.2: +is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== @@ -19478,7 +19474,7 @@ locutus@^2.0.5: resolved "https://registry.yarnpkg.com/locutus/-/locutus-2.0.10.tgz#f903619466a98a4ab76e8b87a5854b55a743b917" integrity sha512-AZg2kCqrquMJ5FehDsBidV0qHl98NrsYtseUClzjAQ3HFnsDBJTCwGVplSQ82t9/QfgahqvTjaKcZqZkHmS0wQ== -lodash-es@^4.17.11, lodash-es@^4.17.5, lodash-es@^4.2.1: +lodash-es@^4.17.11, lodash-es@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== @@ -21844,7 +21840,7 @@ object-identity-map@^1.0.2: dependencies: object.entries "^1.1.0" -object-inspect@^1.6.0: +object-inspect@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== @@ -21859,10 +21855,10 @@ object-inspect@~1.6.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== -object-is@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" - integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY= +object-is@^1.0.1, object-is@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4" + integrity sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ== object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.0.9, object-keys@^1.1.1: version "1.1.1" @@ -21908,13 +21904,13 @@ object.defaults@^1.0.0, object.defaults@^1.1.0: for-own "^1.0.0" isobject "^3.0.0" -object.entries@^1.0.4, object.entries@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.0.tgz#2024fc6d6ba246aee38bdb0ffd5cfbcf371b7519" - integrity sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA== +object.entries@^1.0.4, object.entries@^1.1.0, object.entries@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b" + integrity sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ== dependencies: define-properties "^1.1.3" - es-abstract "^1.12.0" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" has "^1.0.3" @@ -21938,6 +21934,16 @@ object.fromentries@^2.0.1: function-bind "^1.1.1" has "^1.0.3" +object.fromentries@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9" + integrity sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + object.getownpropertydescriptors@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" @@ -21969,13 +21975,13 @@ object.reduce@^1.0.0: for-own "^1.0.0" make-iterator "^1.0.0" -object.values@^1.0.4, object.values@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== +object.values@^1.0.4, object.values@^1.1.0, object.values@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== dependencies: define-properties "^1.1.3" - es-abstract "^1.12.0" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" has "^1.0.3" @@ -23935,14 +23941,7 @@ raf-schd@^4.0.2: resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.2.tgz#bd44c708188f2e84c810bf55fcea9231bcaed8a0" integrity sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ== -raf@^3.1.0, raf@^3.3.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" - integrity sha512-pDP/NMRAXoTfrhCfyfSEwJAKLaxBU9eApMeBPB1TkDouZmvPerIClV8lTAd+uF8ZiTaVl69e1FCxQrAd/VTjGw== - dependencies: - performance-now "^2.1.0" - -raf@^3.4.0: +raf@^3.1.0, raf@^3.3.0, raf@^3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== @@ -24442,11 +24441,6 @@ react-intl@^2.8.0: intl-relativeformat "^2.1.0" invariant "^2.1.1" -react-is@^16.10.2, react-is@^16.9.0: - version "16.11.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.11.0.tgz#b85dfecd48ad1ce469ff558a882ca8e8313928fa" - integrity sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw== - react-is@^16.12.0, react-is@^16.3.1: version "16.12.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" @@ -24467,6 +24461,11 @@ react-is@^16.8.4: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.5.tgz#c54ac229dd66b5afe0de5acbe47647c3da692ff8" integrity sha512-sudt2uq5P/2TznPV4Wtdi+Lnq3yaYW8LfvPKLM9BKD8jJNBkxMVyB0C9/GmVhLw7Jbdmndk/73n7XQGeN9A3QQ== +react-is@^16.9.0: + version "16.11.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.11.0.tgz#b85dfecd48ad1ce469ff558a882ca8e8313928fa" + integrity sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw== + react-is@~16.3.0: version "16.3.2" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.3.2.tgz#f4d3d0e2f5fbb6ac46450641eb2e25bf05d36b22" @@ -24625,19 +24624,7 @@ react-reconciler@^0.22.1: prop-types "^15.6.2" scheduler "^0.16.2" -react-redux@^5.0.7: - version "5.0.7" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8" - integrity sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg== - dependencies: - hoist-non-react-statics "^2.5.0" - invariant "^2.0.0" - lodash "^4.17.5" - lodash-es "^4.17.5" - loose-envify "^1.1.0" - prop-types "^15.6.0" - -react-redux@^5.1.2: +react-redux@^5.0.7, react-redux@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.1.2.tgz#b19cf9e21d694422727bf798e934a916c4080f57" integrity sha512-Ns1G0XXc8hDyH/OcBHOxNgQx9ayH3SPxBnFCOidGKSle8pKihysQw2rG/PmciUQRoclhVBO8HMhiRmGXnDja9Q== @@ -24650,7 +24637,7 @@ react-redux@^5.1.2: react-is "^16.6.0" react-lifecycles-compat "^3.0.0" -react-redux@^7.1.0, react-redux@^7.1.1: +react-redux@^7.1.0, react-redux@^7.1.1, react-redux@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.1.3.tgz#717a3d7bbe3a1b2d535c94885ce04cdc5a33fc79" integrity sha512-uI1wca+ECG9RoVkWQFF4jDMqmaw0/qnvaSvOoL/GA4dNxf6LoV8sUAcNDvE5NWKs4hFpn0t6wswNQnY3f7HT3w== @@ -25281,12 +25268,17 @@ redeyed@~2.1.0: dependencies: esprima "~4.0.0" +reduce-reducers@*, reduce-reducers@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reduce-reducers/-/reduce-reducers-1.0.4.tgz#fb77e751a9eb0201760ac5a605ca8c9c2d0537f8" + integrity sha512-Mb2WZ2bJF597exiqX7owBzrqJ74DHLK3yOQjCyPAaNifRncE8OD0wFIuoMhXxTnHK07+8zZ2SJEKy/qtiyR7vw== + reduce-reducers@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/reduce-reducers/-/reduce-reducers-0.4.3.tgz#8e052618801cd8fc2714b4915adaa8937eb6d66c" integrity sha512-+CNMnI8QhgVMtAt54uQs3kUxC3Sybpa7Y63HR14uGLgI9/QR5ggHvpxwhGGe3wmx5V91YwqQIblN9k5lspAmGw== -redux-actions@2.6.5: +redux-actions@^2.6.5: version "2.6.5" resolved "https://registry.yarnpkg.com/redux-actions/-/redux-actions-2.6.5.tgz#bdca548768ee99832a63910c276def85e821a27e" integrity sha512-pFhEcWFTYNk7DhQgxMGnbsB1H2glqhQJRQrtPb96kD3hWiZRzXHwwmFPswg6V2MjraXRXWNmuP9P84tvdLAJmw== @@ -25302,10 +25294,10 @@ redux-devtools-extension@^2.13.8: resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz#37b982688626e5e4993ff87220c9bbb7cd2d96e1" integrity sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg== -redux-observable@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redux-observable/-/redux-observable-1.0.0.tgz#780ff2455493eedcef806616fe286b454fd15d91" - integrity sha512-6bXnpqWTBeLaLQjXHyN1giXq4nLxCmv+SUkdmiwBgvmVxvDbdmydvL1Z7DGo0WItyzI/kqXQKiucUuTxnrPRkA== +redux-observable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/redux-observable/-/redux-observable-1.2.0.tgz#ff51b6c6be2598e9b5e89fc36639186bb0e669c7" + integrity sha512-yeR90RP2WzZzCxxnQPlh2uFzyfFLsfXu8ROh53jGDPXVqj71uNDMmvi/YKQkd9ofiVoO4OYb1snbowO49tCEMg== redux-saga@^0.16.0: version "0.16.2" @@ -25317,7 +25309,7 @@ redux-thunk@2.2.0: resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5" integrity sha1-5hWhbha0ehmlFXZhM9Hj6Zt4UuU= -redux-thunk@2.3.0: +redux-thunk@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== @@ -25337,7 +25329,7 @@ redux@3.7.2: loose-envify "^1.1.0" symbol-observable "^1.0.3" -redux@4.0.0, redux@^4.0.0: +redux@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.0.tgz#aa698a92b729315d22b34a0553d7e6533555cc03" integrity sha512-NnnHF0h0WVE/hXyrB6OlX67LYRuaf/rJcbWvnHHEPCF/Xa/AZpwhs/20WyqzQae5x4SD2F9nPObgBh2rxAgLiA== @@ -25361,6 +25353,14 @@ redux@^4.0.4: loose-envify "^1.4.0" symbol-observable "^1.2.0" +redux@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" + integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== + dependencies: + loose-envify "^1.4.0" + symbol-observable "^1.2.0" + reflect.ownkeys@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460" @@ -25916,11 +25916,6 @@ requires-regex@^0.3.3: resolved "https://registry.yarnpkg.com/requires-regex/-/requires-regex-0.3.3.tgz#60309eaabbfd5ca8259e090b8b5a94b2144eb0dd" integrity sha1-YDCeqrv9XKglngkLi1qUshROsN0= -reselect@3.0.1, reselect@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147" - integrity sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc= - reselect@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" @@ -26671,17 +26666,17 @@ semver-truncate@^1.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto= -"semver@2 || 3 || 4 || 5", semver@^5.3.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== +"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@5.5.0, semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.5.0: +semver@5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@5.7.0, semver@^5.4.1, semver@^5.6.0, semver@^5.7.0: +semver@5.7.0: version "5.7.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== @@ -27907,13 +27902,13 @@ string.prototype.padstart@^3.0.0: es-abstract "^1.4.3" function-bind "^1.0.2" -string.prototype.trim@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz#75a729b10cfc1be439543dae442129459ce61e3d" - integrity sha512-9EIjYD/WdlvLpn987+ctkLf0FfvBefOCuiEr2henD8X+7jfwPnyvTdmW8OJhj5p+M0/96mBdynLWkxUr+rHlpg== +string.prototype.trim@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz#141233dff32c82bfad80684d7e5f0869ee0fb782" + integrity sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw== dependencies: define-properties "^1.1.3" - es-abstract "^1.13.0" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" string.prototype.trim@~1.1.2: @@ -27925,18 +27920,18 @@ string.prototype.trim@~1.1.2: es-abstract "^1.5.0" function-bind "^1.0.2" -string.prototype.trimleft@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== +string.prototype.trimleft@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" + integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== dependencies: define-properties "^1.1.3" function-bind "^1.1.1" -string.prototype.trimright@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== +string.prototype.trimright@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" + integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== dependencies: define-properties "^1.1.3" function-bind "^1.1.1" @@ -29863,17 +29858,15 @@ typedarray@^0.0.6, typedarray@~0.0.5: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript-fsa-reducers@^0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/typescript-fsa-reducers/-/typescript-fsa-reducers-0.4.5.tgz#58fffb2f6eeca6817c2f656b7e7df2cb1c9d1f84" - integrity sha512-mBIpU4je365qpqp2XWKtNW3rGO/hA4OI+l8vkkXdHLUYukrp3wNeL+e3roUq1F6wa6Kcr0WaMblEQDsIdWHTEQ== - dependencies: - typescript-fsa "^2.0.0" +typescript-fsa-reducers@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/typescript-fsa-reducers/-/typescript-fsa-reducers-1.2.1.tgz#2af1a85f7b88fb0dfb9fa59d5da51a5d7ac6543f" + integrity sha512-Qgn7zEnAU5n3YEWEL5ooEmIWZl9B4QyXD4Y/0DqpUzF0YuTrcsLa7Lht0gFXZ+xqLJXQwo3fEiTfQTDF1fBnMg== -typescript-fsa@^2.0.0, typescript-fsa@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/typescript-fsa/-/typescript-fsa-2.5.0.tgz#1baec01b5e8f5f34c322679d1327016e9e294faf" - integrity sha1-G67AG16PXzTDImedEycBbp4pT68= +typescript-fsa@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/typescript-fsa/-/typescript-fsa-3.0.0.tgz#3ad1cb915a67338e013fc21f67c9b3e0e110c912" + integrity sha512-xiXAib35i0QHl/+wMobzPibjAH5TJLDj+qGq5jwVLG9qR4FUswZURBw2qihBm0m06tHoyb3FzpnJs1GRhRwVag== typescript@3.5.3, typescript@3.7.2, typescript@^3.0.1, typescript@^3.0.3, typescript@^3.2.2, typescript@^3.3.3333, typescript@^3.4.5, typescript@~3.7.2: version "3.7.2" From 84be2620751dce74f6272d6783a3a0d85e78d6ae Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Mon, 17 Feb 2020 10:59:07 +0100 Subject: [PATCH 05/21] [ML] New Platform server shim: update indices routes (#57685) * [ML] NP indices routes * [ML] fix error function * [ML] fix createAndOpenUrl function --- .../components/anomalies_table/links_menu.js | 70 +++++++++---------- .../plugins/ml/server/routes/apidoc.json | 4 +- .../plugins/ml/server/routes/indices.js | 28 -------- .../plugins/ml/server/routes/indices.ts | 49 +++++++++++++ 4 files changed, 87 insertions(+), 64 deletions(-) delete mode 100644 x-pack/legacy/plugins/ml/server/routes/indices.js create mode 100644 x-pack/legacy/plugins/ml/server/routes/indices.ts diff --git a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js index c16dc37097b13..f161e37efa8d8 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js +++ b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js @@ -236,26 +236,26 @@ class LinksMenuUI extends Component { let i = 0; findFieldType(datafeedIndices[i]); - function findFieldType(index) { - getFieldTypeFromMapping(index, categorizationFieldName) - .then(resp => { - if (resp !== '') { - createAndOpenUrl(index, resp); - } else { - i++; - if (i < datafeedIndices.length) { - findFieldType(datafeedIndices[i]); - } else { - error(); - } - } + const error = () => { + console.log( + `viewExamples(): error finding type of field ${categorizationFieldName} in indices:`, + datafeedIndices + ); + const { toasts } = this.props.kibana.services.notifications; + toasts.addDanger( + i18n.translate('xpack.ml.anomaliesTable.linksMenu.noMappingCouldBeFoundErrorMessage', { + defaultMessage: + 'Unable to view examples of documents with mlcategory {categoryId} ' + + 'as no mapping could be found for the categorization field {categorizationFieldName}', + values: { + categoryId, + categorizationFieldName, + }, }) - .catch(() => { - error(); - }); - } + ); + }; - function createAndOpenUrl(index, categorizationFieldType) { + const createAndOpenUrl = (index, categorizationFieldType) => { // Find the ID of the index pattern with a title attribute which matches the // index configured in the datafeed. If a Kibana index pattern has not been created // for this index, then the user will see a warning message on the Discover tab advising @@ -340,25 +340,25 @@ class LinksMenuUI extends Component { }) ); }); - } + }; - function error() { - console.log( - `viewExamples(): error finding type of field ${categorizationFieldName} in indices:`, - datafeedIndices - ); - const { toasts } = this.props.kibana.services.notifications; - toasts.addDanger( - i18n.translate('xpack.ml.anomaliesTable.linksMenu.noMappingCouldBeFoundErrorMessage', { - defaultMessage: - 'Unable to view examples of documents with mlcategory {categoryId} ' + - 'as no mapping could be found for the categorization field {categorizationFieldName}', - values: { - categoryId, - categorizationFieldName, - }, + function findFieldType(index) { + getFieldTypeFromMapping(index, categorizationFieldName) + .then(resp => { + if (resp !== '') { + createAndOpenUrl(index, resp); + } else { + i++; + if (i < datafeedIndices.length) { + findFieldType(datafeedIndices[i]); + } else { + error(); + } + } }) - ); + .catch(() => { + error(); + }); } }; diff --git a/x-pack/legacy/plugins/ml/server/routes/apidoc.json b/x-pack/legacy/plugins/ml/server/routes/apidoc.json index be1554bf55f78..35215f8008ec3 100644 --- a/x-pack/legacy/plugins/ml/server/routes/apidoc.json +++ b/x-pack/legacy/plugins/ml/server/routes/apidoc.json @@ -76,6 +76,8 @@ "CreateFilter", "UpdateFilter", "DeleteFilter", - "GetFiltersStats" + "GetFiltersStats", + "Indices", + "FieldCaps" ] } diff --git a/x-pack/legacy/plugins/ml/server/routes/indices.js b/x-pack/legacy/plugins/ml/server/routes/indices.js deleted file mode 100644 index 309b41e53eef5..0000000000000 --- a/x-pack/legacy/plugins/ml/server/routes/indices.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { callWithRequestFactory } from '../client/call_with_request_factory'; -import { wrapError } from '../client/errors'; - -export function indicesRoutes({ commonRouteConfig, elasticsearchPlugin, route }) { - route({ - method: 'POST', - path: '/api/ml/indices/field_caps', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - const index = request.payload.index; - let fields = '*'; - if (request.payload.fields !== undefined && Array.isArray(request.payload.fields)) { - fields = request.payload.fields.join(','); - } - - return callWithRequest('fieldCaps', { index, fields }).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); -} diff --git a/x-pack/legacy/plugins/ml/server/routes/indices.ts b/x-pack/legacy/plugins/ml/server/routes/indices.ts new file mode 100644 index 0000000000000..0ee15f1321e9c --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/routes/indices.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { wrapError } from '../client/error_wrapper'; +import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { RouteInitialization } from '../new_platform/plugin'; + +/** + * Indices routes. + */ +export function indicesRoutes({ xpackMainPlugin, router }: RouteInitialization) { + /** + * @apiGroup Indices + * + * @api {post} /api/ml/indices/field_caps + * @apiName FieldCaps + * @apiDescription Retrieves the capabilities of fields among multiple indices. + */ + router.post( + { + path: '/api/ml/indices/field_caps', + validate: { + body: schema.object({ + index: schema.maybe(schema.string()), + fields: schema.maybe(schema.arrayOf(schema.string())), + }), + }, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const { + body: { index, fields: requestFields }, + } = request; + const fields = + requestFields !== undefined && Array.isArray(requestFields) + ? requestFields.join(',') + : '*'; + const result = await context.ml!.mlClient.callAsCurrentUser('fieldCaps', { index, fields }); + return response.ok({ body: result }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); +} From 26fdc4a6b373dac5ec110a34ef0472046dc438b7 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Mon, 17 Feb 2020 11:03:57 +0100 Subject: [PATCH 06/21] [Upgrade Assistant] Fix filter deprecations search filter (#57541) * Made eui search field not a controlled component Added validateRegExpString util * Update error message display. Use EuiCallOut and i18n to replicate other search filter behaviour, e.g. index management. * Remove unused variable * Update Jest snapshot * Updated layout for callout The previous callout layout looked off-center next to the controls in the table. * Update copy and remove intl Update "Filter Invalid:" to sentence case Remove inject intl wrapper from CheckupControls component Remove unnecessary grow={true} * Updated Jest component snapshot Co-authored-by: Elastic Machine --- .../__snapshots__/checkup_tab.test.tsx.snap | 3 +- .../components/tabs/checkup/checkup_tab.tsx | 3 +- .../components/tabs/checkup/controls.tsx | 121 ++++++++++++------ .../public/np_ready/application/utils.test.ts | 20 +++ .../public/np_ready/application/utils.ts | 19 +++ 5 files changed, 121 insertions(+), 45 deletions(-) create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.test.ts create mode 100644 x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.ts diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap index eb76498b55f4c..da1760d3773d4 100644 --- a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/components/tabs/checkup/__snapshots__/checkup_tab.test.tsx.snap @@ -57,7 +57,7 @@ exports[`CheckupTab render with deprecations 1`] = ` - @@ -143,7 +143,6 @@ export class CheckupTab extends UpgradeAssistantTabComponent void; currentFilter: LevelFilterOption; onFilterChange: (filter: LevelFilterOption) => void; - search: string; onSearchChange: (filter: string) => void; availableGroupByOptions: GroupByOption[]; currentGroupBy: GroupByOption; onGroupByChange: (groupBy: GroupByOption) => void; } -export const CheckupControlsUI: FunctionComponent = ({ +export const CheckupControls: FunctionComponent = ({ allDeprecations, loadingState, loadData, currentFilter, onFilterChange, - search, onSearchChange, availableGroupByOptions, currentGroupBy, onGroupByChange, - intl, -}) => ( - - - onSearchChange(e.target.value)} - /> - - - {/* These two components provide their own EuiFlexItem wrappers */} - - +}) => { + const [searchTermError, setSearchTermError] = useState(null); + const filterInvalid = Boolean(searchTermError); + return ( + + + + + { + const string = e.target.value; + const errorMessage = validateRegExpString(string); + if (errorMessage) { + // Emit an empty search term to listeners if search term is invalid. + onSearchChange(''); + setSearchTermError(errorMessage); + } else { + onSearchChange(e.target.value); + if (searchTermError) { + setSearchTermError(null); + } + } + }} + /> + - - - - - - -); + {/* These two components provide their own EuiFlexItem wrappers */} + + -export const CheckupControls = injectI18n(CheckupControlsUI); + + + + + + + + {filterInvalid && ( + + + + )} + + ); +}; diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.test.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.test.ts new file mode 100644 index 0000000000000..067f11798e151 --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.test.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { validateRegExpString } from './utils'; + +describe('validRegExpString', () => { + it('correctly returns false for invalid strings', () => { + expect(validateRegExpString('?asd')).toContain(`Invalid regular expression`); + expect(validateRegExpString('*asd')).toContain(`Invalid regular expression`); + expect(validateRegExpString('(')).toContain(`Invalid regular expression`); + }); + + it('correctly returns true for valid strings', () => { + expect(validateRegExpString('asd')).toBe(''); + expect(validateRegExpString('.*asd')).toBe(''); + expect(validateRegExpString('')).toBe(''); + }); +}); diff --git a/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.ts b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.ts new file mode 100644 index 0000000000000..6a1f32fe8f20b --- /dev/null +++ b/x-pack/legacy/plugins/upgrade_assistant/public/np_ready/application/utils.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { pipe } from 'fp-ts/lib/pipeable'; +import { tryCatch, fold } from 'fp-ts/lib/Either'; + +export const validateRegExpString = (s: string) => + pipe( + tryCatch( + () => new RegExp(s), + e => (e as Error).message + ), + fold( + (errorMessage: string) => errorMessage, + () => '' + ) + ); From 3d7bae4ed24b8b5777ee217f304a1203e5753880 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Mon, 17 Feb 2020 11:06:20 +0100 Subject: [PATCH 07/21] Move Ace XJSON lexer-rules, worker and utils to es_ui_shared (#57563) * Move mode and lexer rules to shared space * Update searchprofiler mode rules * Moved x-json worker out of searchprofiler and into es_ui_shared (for use in Watcher) Renamed ace/mode -> ace/modes * Moved collapse and expand literal string functions to es_ui_shared * Fix some imports Enable Watcher editor to parse XJson using XJsonMode * Fix imports Import JSON highlight rules in XJSONHighlight rules * Move console_lang, fix Jest tests Exporting console_lang through the es_ui_shared/public barrel caused the XJsonMode to imported to a index_management too and any other plugin that may import something from that directory. console_lang was moved to it's own top level directory es_ui_shared/console_lang. We also included a mock for tests using XJsonMode to import from console_lang. * Fixed OSS Jest tests Console Jest tests were still failing because they did not mock out the raw-loader imported worker file * Expand triple quotes in editor Upon entering the advanced watcher creation view, the JSON should be scanned for triple quote expansion * Bring all editors themes in line Editors had github theme, which diverged from the textmate theme used in Console and SearchProfiler * Added XJSON mode to simulate alternative input editor Slight refactor to the logic for using XJSON mode. Created an adhoc hook for wrapping the logic of useState and moved lanugage util imports there too to reduce the number of imports in both the watcher form and simulate tabs in advanced creation. * Moved x-json worker to x-pack x-json worker is currently only used inside of x-pack. Also testing for if this will fix the CI/prod build Co-authored-by: Elastic Machine --- .../legacy/console_editor/editor_output.tsx | 4 +- .../send_request_to_es.ts | 9 +- .../models/legacy_core_editor/mode/input.js | 2 +- .../mode/input_highlight_rules.js | 4 +- .../mode/output_highlight_rules.js | 4 +- .../models/legacy_core_editor/mode/script.js | 19 +- .../legacy_core_editor/mode/worker/index.d.ts | 20 ++ .../__tests__/sense_editor.test.js | 4 +- .../models/sense_editor/sense_editor.ts | 6 +- .../ace_token_provider/token_provider.test.ts | 1 - .../public/lib/autocomplete/autocomplete.ts | 2 +- .../public/lib/utils/__tests__/utils.test.js | 179 +++++++----------- .../public/lib/utils/{utils.ts => index.ts} | 57 +----- .../console_lang/ace/modes/index.d.ts | 32 ++++ .../console_lang/ace/modes/index.js | 27 +++ .../elasticsearch_sql_highlight_rules.ts | 0 .../ace/modes/lexer_rules/index.js | 22 +++ .../lexer_rules}/script_highlight_rules.js | 0 .../lexer_rules}/x_json_highlight_rules.js | 31 ++- .../console_lang/ace/modes/x_json/index.ts | 20 ++ .../ace/modes/x_json/x_json_mode.ts | 40 ++++ .../es_ui_shared/console_lang/index.ts | 29 +++ .../es_ui_shared/console_lang/lib/index.ts | 20 ++ .../json_xjson_translation_tools.test.ts | 65 +++++++ .../__tests__/utils_string_collapsing.txt | 0 .../__tests__/utils_string_expanding.txt | 0 .../lib/json_xjson_translation_tools/index.ts | 71 +++++++ src/plugins/es_ui_shared/public/index.ts | 2 +- .../console_lang/ace/modes/index.ts | 7 + .../console_lang/ace/modes/x_json/index.ts | 7 + .../ace/modes/x_json}/worker/index.ts | 0 .../ace/modes/x_json}/worker/worker.d.ts | 0 .../ace/modes/x_json}/worker/worker.js | 0 .../console_lang/ace/modes/x_json/x_json.ts | 34 ++++ .../es_ui_shared/console_lang/index.ts | 7 + .../es_ui_shared/console_lang/mocks.ts | 9 + .../application/containers/main/main.tsx | 1 - .../public/application/editor/editor.test.tsx | 4 +- .../public/application/editor/init_editor.ts | 2 +- .../editor/x_json_highlight_rules.ts | 139 -------------- .../public/application/editor/x_json_mode.ts | 54 ------ .../utils/check_for_json_errors.ts | 7 +- .../watch_create_json.test.ts | 2 + .../watch_create_threshold.test.tsx | 3 + .../client_integration/watch_edit.test.ts | 2 + .../client_integration/watch_list.test.ts | 1 + .../client_integration/watch_status.test.ts | 2 + .../json_watch_edit/json_watch_edit_form.tsx | 16 +- .../json_watch_edit_simulate.tsx | 15 +- .../json_watch_edit/use_x_json_mode.ts | 24 +++ .../action_fields/webhook_action_fields.tsx | 2 +- 51 files changed, 591 insertions(+), 417 deletions(-) create mode 100644 src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.d.ts rename src/plugins/console/public/lib/utils/{utils.ts => index.ts} (59%) create mode 100644 src/plugins/es_ui_shared/console_lang/ace/modes/index.d.ts create mode 100644 src/plugins/es_ui_shared/console_lang/ace/modes/index.js rename src/plugins/{console/public/application/models/legacy_core_editor/mode => es_ui_shared/console_lang/ace/modes/lexer_rules}/elasticsearch_sql_highlight_rules.ts (100%) create mode 100644 src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/index.js rename src/plugins/{console/public/application/models/legacy_core_editor/mode => es_ui_shared/console_lang/ace/modes/lexer_rules}/script_highlight_rules.js (100%) rename src/plugins/{console/public/application/models/legacy_core_editor/mode => es_ui_shared/console_lang/ace/modes/lexer_rules}/x_json_highlight_rules.js (85%) create mode 100644 src/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts create mode 100644 src/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json_mode.ts create mode 100644 src/plugins/es_ui_shared/console_lang/index.ts create mode 100644 src/plugins/es_ui_shared/console_lang/lib/index.ts create mode 100644 src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts rename src/plugins/{console/public/lib/utils => es_ui_shared/console_lang/lib/json_xjson_translation_tools}/__tests__/utils_string_collapsing.txt (100%) rename src/plugins/{console/public/lib/utils => es_ui_shared/console_lang/lib/json_xjson_translation_tools}/__tests__/utils_string_expanding.txt (100%) create mode 100644 src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/index.ts create mode 100644 x-pack/plugins/es_ui_shared/console_lang/ace/modes/index.ts create mode 100644 x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts rename x-pack/plugins/{searchprofiler/public/application/editor => es_ui_shared/console_lang/ace/modes/x_json}/worker/index.ts (100%) rename x-pack/plugins/{searchprofiler/public/application/editor => es_ui_shared/console_lang/ace/modes/x_json}/worker/worker.d.ts (100%) rename x-pack/plugins/{searchprofiler/public/application/editor => es_ui_shared/console_lang/ace/modes/x_json}/worker/worker.js (100%) create mode 100644 x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json.ts create mode 100644 x-pack/plugins/es_ui_shared/console_lang/index.ts create mode 100644 x-pack/plugins/es_ui_shared/console_lang/mocks.ts delete mode 100644 x-pack/plugins/searchprofiler/public/application/editor/x_json_highlight_rules.ts delete mode 100644 x-pack/plugins/searchprofiler/public/application/editor/x_json_mode.ts create mode 100644 x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/use_x_json_mode.ts diff --git a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx index e232e41902cbb..ca468f85275a8 100644 --- a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx +++ b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor_output.tsx @@ -26,7 +26,7 @@ import { useRequestReadContext, } from '../../../../contexts'; -import * as utils from '../../../../../lib/utils/utils'; +import { expandLiteralStrings } from '../../../../../../../es_ui_shared/console_lang/lib'; import { subscribeResizeChecker } from '../subscribe_console_resize_checker'; import { applyCurrentSettings } from './apply_editor_settings'; @@ -67,7 +67,7 @@ function EditorOutputUI() { editor.update( data .map(d => d.response.value as string) - .map(readOnlySettings.tripleQuotes ? utils.expandLiteralStrings : a => a) + .map(readOnlySettings.tripleQuotes ? expandLiteralStrings : a => a) .join('\n') ); } else if (error) { diff --git a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts b/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts index 35d9865ee4ccb..102f90a9feb6f 100644 --- a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts +++ b/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts @@ -17,10 +17,11 @@ * under the License. */ -import * as utils from '../../../lib/utils/utils'; +import { extractDeprecationMessages } from '../../../lib/utils'; +import { collapseLiteralStrings } from '../../../../../es_ui_shared/console_lang/lib'; // @ts-ignore import * as es from '../../../lib/es/es'; -import { BaseResponseType } from '../../../types/common'; +import { BaseResponseType } from '../../../types'; export interface EsRequestArgs { requests: any; @@ -73,7 +74,7 @@ export function sendRequestToES(args: EsRequestArgs): Promise const req = requests.shift(); const esPath = req.url; const esMethod = req.method; - let esData = utils.collapseLiteralStrings(req.data.join('\n')); + let esData = collapseLiteralStrings(req.data.join('\n')); if (esData) { esData += '\n'; } // append a new line for bulk requests. @@ -97,7 +98,7 @@ export function sendRequestToES(args: EsRequestArgs): Promise const warnings = xhr.getResponseHeader('warning'); if (warnings) { - const deprecationMessages = utils.extractDeprecationMessages(warnings); + const deprecationMessages = extractDeprecationMessages(warnings); value = deprecationMessages.join('\n') + '\n' + value; } diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js index da101b61f8035..d763db7ae5d79 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js @@ -18,6 +18,7 @@ */ import ace from 'brace'; +import { workerModule } from './worker'; const oop = ace.acequire('ace/lib/oop'); const TextMode = ace.acequire('ace/mode/text').Mode; @@ -29,7 +30,6 @@ const WorkerClient = ace.acequire('ace/worker/worker_client').WorkerClient; const AceTokenizer = ace.acequire('ace/tokenizer').Tokenizer; const HighlightRules = require('./input_highlight_rules').InputHighlightRules; -import { workerModule } from './worker'; export function Mode() { this.$tokenizer = new AceTokenizer(new HighlightRules().getRules()); diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js index 842736428e8bb..2c1b30f806f95 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js @@ -18,7 +18,7 @@ */ const ace = require('brace'); -import { addToRules } from './x_json_highlight_rules'; +import { addXJsonToRules } from '../../../../../../es_ui_shared/console_lang'; export function addEOL(tokens, reg, nextIfEOL, normalNext) { if (typeof reg === 'object') { @@ -101,7 +101,7 @@ export function InputHighlightRules() { ), }; - addToRules(this); + addXJsonToRules(this); if (this.constructor === InputHighlightRules) { this.normalizeRules(); diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js index 920bdff1798db..e27222ebd65e9 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js @@ -19,7 +19,7 @@ const ace = require('brace'); import 'brace/mode/json'; -import { addToRules } from './x_json_highlight_rules'; +import { addXJsonToRules } from '../../../../../../es_ui_shared/console_lang'; const oop = ace.acequire('ace/lib/oop'); const JsonHighlightRules = ace.acequire('ace/mode/json_highlight_rules').JsonHighlightRules; @@ -27,7 +27,7 @@ const JsonHighlightRules = ace.acequire('ace/mode/json_highlight_rules').JsonHig export function OutputJsonHighlightRules() { this.$rules = {}; - addToRules(this, 'start'); + addXJsonToRules(this, 'start'); this.$rules.start.unshift( { diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js index b6b74c6377233..13ae329380221 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js @@ -18,17 +18,15 @@ */ import ace from 'brace'; +import { ScriptHighlightRules } from '../../../../../../es_ui_shared/console_lang'; const oop = ace.acequire('ace/lib/oop'); const TextMode = ace.acequire('ace/mode/text').Mode; const MatchingBraceOutdent = ace.acequire('ace/mode/matching_brace_outdent').MatchingBraceOutdent; const CstyleBehaviour = ace.acequire('ace/mode/behaviour/cstyle').CstyleBehaviour; const CStyleFoldMode = ace.acequire('ace/mode/folding/cstyle').FoldMode; -//const WorkerClient = ace.acequire('ace/worker/worker_client').WorkerClient; ace.acequire('ace/tokenizer'); -const ScriptHighlightRules = require('./script_highlight_rules').ScriptHighlightRules; - export function ScriptMode() { this.$outdent = new MatchingBraceOutdent(); this.$behaviour = new CstyleBehaviour(); @@ -57,19 +55,4 @@ oop.inherits(ScriptMode, TextMode); this.autoOutdent = function(state, doc, row) { this.$outdent.autoOutdent(doc, row); }; - - // this.createWorker = function (session) { - // const worker = new WorkerClient(['ace', 'sense_editor'], 'sense_editor/mode/worker', 'SenseWorker', 'sense_editor/mode/worker'); - // worker.attachToDocument(session.getDocument()); - - // worker.on('error', function (e) { - // session.setAnnotations([e.data]); - // }); - - // worker.on('ok', function (anno) { - // session.setAnnotations(anno.data); - // }); - - // return worker; - // }; }.call(ScriptMode.prototype)); diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.d.ts b/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.d.ts new file mode 100644 index 0000000000000..c7ceb6a95b896 --- /dev/null +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/index.d.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 declare const workerModule: { id: string; src: string }; diff --git a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js index a66bc20685df7..63f97345bc9ff 100644 --- a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js +++ b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js @@ -22,8 +22,8 @@ import $ from 'jquery'; import _ from 'lodash'; import { create } from '../create'; +import { collapseLiteralStrings } from '../../../../../../es_ui_shared/console_lang/lib'; const editorInput1 = require('./editor_input1.txt'); -const utils = require('../../../../lib/utils/utils'); describe('Editor', () => { let input; @@ -331,7 +331,7 @@ describe('Editor', () => { const expected = { method: 'POST', url: '_search', - data: [utils.collapseLiteralStrings(simpleRequest.data)], + data: [collapseLiteralStrings(simpleRequest.data)], }; compareRequest(request, expected); diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts index 1271f167c6cc1..f559f5dfcd707 100644 --- a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts +++ b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts @@ -19,7 +19,9 @@ import _ from 'lodash'; import RowParser from '../../../lib/row_parser'; -import * as utils from '../../../lib/utils/utils'; +import { collapseLiteralStrings } from '../../../../../es_ui_shared/console_lang/lib'; +import * as utils from '../../../lib/utils'; + // @ts-ignore import * as es from '../../../lib/es/es'; @@ -480,7 +482,7 @@ export class SenseEditor { let ret = 'curl -X' + esMethod + ' "' + url + '"'; if (esData && esData.length) { ret += " -H 'Content-Type: application/json' -d'\n"; - const dataAsString = utils.collapseLiteralStrings(esData.join('\n')); + const dataAsString = collapseLiteralStrings(esData.join('\n')); // since Sense doesn't allow single quote json string any single qoute is within a string. ret += dataAsString.replace(/'/g, '\\"'); if (esData.length > 1) { diff --git a/src/plugins/console/public/lib/ace_token_provider/token_provider.test.ts b/src/plugins/console/public/lib/ace_token_provider/token_provider.test.ts index 00bfe32c85906..d5465ebe96514 100644 --- a/src/plugins/console/public/lib/ace_token_provider/token_provider.test.ts +++ b/src/plugins/console/public/lib/ace_token_provider/token_provider.test.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - import '../../application/models/sense_editor/sense_editor.test.mocks'; import $ from 'jquery'; diff --git a/src/plugins/console/public/lib/autocomplete/autocomplete.ts b/src/plugins/console/public/lib/autocomplete/autocomplete.ts index ac8fa1ea48caa..e09024ccfc859 100644 --- a/src/plugins/console/public/lib/autocomplete/autocomplete.ts +++ b/src/plugins/console/public/lib/autocomplete/autocomplete.ts @@ -29,7 +29,7 @@ import { // @ts-ignore } from '../kb/kb'; -import * as utils from '../utils/utils'; +import * as utils from '../utils'; // @ts-ignore import { populateContext } from './engine'; diff --git a/src/plugins/console/public/lib/utils/__tests__/utils.test.js b/src/plugins/console/public/lib/utils/__tests__/utils.test.js index f6828f354a1bc..6115be3c84ed9 100644 --- a/src/plugins/console/public/lib/utils/__tests__/utils.test.js +++ b/src/plugins/console/public/lib/utils/__tests__/utils.test.js @@ -17,125 +17,80 @@ * under the License. */ -const _ = require('lodash'); -const utils = require('../utils'); -const collapsingTests = require('./utils_string_collapsing.txt'); -const expandingTests = require('./utils_string_expanding.txt'); +const utils = require('../'); describe('Utils class', () => { - describe('collapseLiteralStrings', () => { - it('will collapse multiline strings', () => { - const multiline = '{ "foo": """bar\nbaz""" }'; - expect(utils.collapseLiteralStrings(multiline)).toEqual('{ "foo": "bar\\nbaz" }'); - }); + test('extract deprecation messages', function() { + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning" "Mon, 27 Feb 2017 14:52:14 GMT"' + ) + ).toEqual(['#! Deprecation: this is a warning']); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning"' + ) + ).toEqual(['#! Deprecation: this is a warning']); - it('will collapse multiline strings with CRLF endings', () => { - const multiline = '{ "foo": """bar\r\nbaz""" }'; - expect(utils.collapseLiteralStrings(multiline)).toEqual('{ "foo": "bar\\r\\nbaz" }'); - }); - }); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning" "Mon, 27 Feb 2017 14:52:14 GMT", 299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a second warning" "Mon, 27 Feb 2017 14:52:14 GMT"' + ) + ).toEqual(['#! Deprecation: this is a warning', '#! Deprecation: this is a second warning']); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning", 299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a second warning"' + ) + ).toEqual(['#! Deprecation: this is a warning', '#! Deprecation: this is a second warning']); - _.each(collapsingTests.split(/^=+$/m), function(fixture) { - if (fixture.trim() === '') { - return; - } - fixture = fixture.split(/^-+$/m); - const name = fixture[0].trim(); - const expanded = fixture[1].trim(); - const collapsed = fixture[2].trim(); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes a comma" "Mon, 27 Feb 2017 14:52:14 GMT"' + ) + ).toEqual(['#! Deprecation: this is a warning, and it includes a comma']); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes a comma"' + ) + ).toEqual(['#! Deprecation: this is a warning, and it includes a comma']); - test('Literal collapse - ' + name, function() { - expect(utils.collapseLiteralStrings(expanded)).toEqual(collapsed); - }); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes an escaped backslash \\\\ and a pair of \\"escaped quotes\\"" "Mon, 27 Feb 2017 14:52:14 GMT"' + ) + ).toEqual([ + '#! Deprecation: this is a warning, and it includes an escaped backslash \\ and a pair of "escaped quotes"', + ]); + expect( + utils.extractDeprecationMessages( + '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes an escaped backslash \\\\ and a pair of \\"escaped quotes\\""' + ) + ).toEqual([ + '#! Deprecation: this is a warning, and it includes an escaped backslash \\ and a pair of "escaped quotes"', + ]); }); - _.each(expandingTests.split(/^=+$/m), function(fixture) { - if (fixture.trim() === '') { - return; - } - fixture = fixture.split(/^-+$/m); - const name = fixture[0].trim(); - const collapsed = fixture[1].trim(); - const expanded = fixture[2].trim(); - - test('Literal expand - ' + name, function() { - expect(utils.expandLiteralStrings(collapsed)).toEqual(expanded); - }); - - test('extract deprecation messages', function() { - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning" "Mon, 27 Feb 2017 14:52:14 GMT"' - ) - ).toEqual(['#! Deprecation: this is a warning']); - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning"' - ) - ).toEqual(['#! Deprecation: this is a warning']); - - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning" "Mon, 27 Feb 2017 14:52:14 GMT", 299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a second warning" "Mon, 27 Feb 2017 14:52:14 GMT"' - ) - ).toEqual(['#! Deprecation: this is a warning', '#! Deprecation: this is a second warning']); - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning", 299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a second warning"' - ) - ).toEqual(['#! Deprecation: this is a warning', '#! Deprecation: this is a second warning']); - - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes a comma" "Mon, 27 Feb 2017 14:52:14 GMT"' - ) - ).toEqual(['#! Deprecation: this is a warning, and it includes a comma']); - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes a comma"' - ) - ).toEqual(['#! Deprecation: this is a warning, and it includes a comma']); - - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes an escaped backslash \\\\ and a pair of \\"escaped quotes\\"" "Mon, 27 Feb 2017 14:52:14 GMT"' - ) - ).toEqual([ - '#! Deprecation: this is a warning, and it includes an escaped backslash \\ and a pair of "escaped quotes"', - ]); - expect( - utils.extractDeprecationMessages( - '299 Elasticsearch-6.0.0-alpha1-SNAPSHOT-abcdef1 "this is a warning, and it includes an escaped backslash \\\\ and a pair of \\"escaped quotes\\""' - ) - ).toEqual([ - '#! Deprecation: this is a warning, and it includes an escaped backslash \\ and a pair of "escaped quotes"', - ]); - }); - - test('unescape', function() { - expect(utils.unescape('escaped backslash \\\\')).toEqual('escaped backslash \\'); - expect(utils.unescape('a pair of \\"escaped quotes\\"')).toEqual( - 'a pair of "escaped quotes"' - ); - expect(utils.unescape('escaped quotes do not have to come in pairs: \\"')).toEqual( - 'escaped quotes do not have to come in pairs: "' - ); - }); + test('unescape', function() { + expect(utils.unescape('escaped backslash \\\\')).toEqual('escaped backslash \\'); + expect(utils.unescape('a pair of \\"escaped quotes\\"')).toEqual('a pair of "escaped quotes"'); + expect(utils.unescape('escaped quotes do not have to come in pairs: \\"')).toEqual( + 'escaped quotes do not have to come in pairs: "' + ); + }); - test('split on unquoted comma followed by space', function() { - expect(utils.splitOnUnquotedCommaSpace('a, b')).toEqual(['a', 'b']); - expect(utils.splitOnUnquotedCommaSpace('a,b, c')).toEqual(['a,b', 'c']); - expect(utils.splitOnUnquotedCommaSpace('"a, b"')).toEqual(['"a, b"']); - expect(utils.splitOnUnquotedCommaSpace('"a, b", c')).toEqual(['"a, b"', 'c']); - expect(utils.splitOnUnquotedCommaSpace('"a, b\\", c"')).toEqual(['"a, b\\", c"']); - expect(utils.splitOnUnquotedCommaSpace(', a, b')).toEqual(['', 'a', 'b']); - expect(utils.splitOnUnquotedCommaSpace('a, b, ')).toEqual(['a', 'b', '']); - expect(utils.splitOnUnquotedCommaSpace('\\"a, b", "c, d\\", e", f"')).toEqual([ - '\\"a', - 'b", "c', - 'd\\"', - 'e", f"', - ]); - }); + test('split on unquoted comma followed by space', function() { + expect(utils.splitOnUnquotedCommaSpace('a, b')).toEqual(['a', 'b']); + expect(utils.splitOnUnquotedCommaSpace('a,b, c')).toEqual(['a,b', 'c']); + expect(utils.splitOnUnquotedCommaSpace('"a, b"')).toEqual(['"a, b"']); + expect(utils.splitOnUnquotedCommaSpace('"a, b", c')).toEqual(['"a, b"', 'c']); + expect(utils.splitOnUnquotedCommaSpace('"a, b\\", c"')).toEqual(['"a, b\\", c"']); + expect(utils.splitOnUnquotedCommaSpace(', a, b')).toEqual(['', 'a', 'b']); + expect(utils.splitOnUnquotedCommaSpace('a, b, ')).toEqual(['a', 'b', '']); + expect(utils.splitOnUnquotedCommaSpace('\\"a, b", "c, d\\", e", f"')).toEqual([ + '\\"a', + 'b", "c', + 'd\\"', + 'e", f"', + ]); }); }); diff --git a/src/plugins/console/public/lib/utils/utils.ts b/src/plugins/console/public/lib/utils/index.ts similarity index 59% rename from src/plugins/console/public/lib/utils/utils.ts rename to src/plugins/console/public/lib/utils/index.ts index 0b10938abe704..f66c952dd3af7 100644 --- a/src/plugins/console/public/lib/utils/utils.ts +++ b/src/plugins/console/public/lib/utils/index.ts @@ -18,6 +18,10 @@ */ import _ from 'lodash'; +import { + expandLiteralStrings, + collapseLiteralStrings, +} from '../../../../es_ui_shared/console_lang/lib'; export function textFromRequest(request: any) { let data = request.data; @@ -56,59 +60,6 @@ export function formatRequestBodyDoc(data: string[], indent: boolean) { }; } -export function collapseLiteralStrings(data: any) { - const splitData = data.split(`"""`); - for (let idx = 1; idx < splitData.length - 1; idx += 2) { - splitData[idx] = JSON.stringify(splitData[idx]); - } - return splitData.join(''); -} - -/* - The following regex describes global match on: - 1. one colon followed by any number of space characters - 2. one double quote (not escaped, special case for JSON in JSON). - 3. greedily match any non double quote and non newline char OR any escaped double quote char (non-capturing). - 4. handle a special case where an escaped slash may be the last character - 5. one double quote - - For instance: `: "some characters \" here"` - Will match and be expanded to: `"""some characters " here"""` - - */ - -const LITERAL_STRING_CANDIDATES = /((:[\s\r\n]*)([^\\])"(\\"|[^"\n])*\\?")/g; - -export function expandLiteralStrings(data: string) { - return data.replace(LITERAL_STRING_CANDIDATES, (match, string) => { - // Expand to triple quotes if there are _any_ slashes - if (string.match(/\\./)) { - const firstDoubleQuoteIdx = string.indexOf('"'); - const lastDoubleQuoteIdx = string.lastIndexOf('"'); - - // Handle a special case where we may have a value like "\"test\"". We don't - // want to expand this to """"test"""" - so we terminate before processing the string - // further if we detect this either at the start or end of the double quote section. - - if (string[firstDoubleQuoteIdx + 1] === '\\' && string[firstDoubleQuoteIdx + 2] === '"') { - return string; - } - - if (string[lastDoubleQuoteIdx - 1] === '"' && string[lastDoubleQuoteIdx - 2] === '\\') { - return string; - } - - const colonAndAnySpacing = string.slice(0, firstDoubleQuoteIdx); - const rawStringifiedValue = string.slice(firstDoubleQuoteIdx, string.length); - // Remove one level of JSON stringification - const jsonValue = JSON.parse(rawStringifiedValue); - return `${colonAndAnySpacing}"""${jsonValue}"""`; - } else { - return string; - } - }); -} - export function extractDeprecationMessages(warnings: string) { // pattern for valid warning header const re = /\d{3} [0-9a-zA-Z!#$%&'*+-.^_`|~]+ \"((?:\t| |!|[\x23-\x5b]|[\x5d-\x7e]|[\x80-\xff]|\\\\|\\")*)\"(?: \"[^"]*\")?/; diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/index.d.ts b/src/plugins/es_ui_shared/console_lang/ace/modes/index.d.ts new file mode 100644 index 0000000000000..06c9f9a51ea68 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/ace/modes/index.d.ts @@ -0,0 +1,32 @@ +/* + * 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 { Editor } from 'brace'; + +export declare const ElasticsearchSqlHighlightRules: FunctionConstructor; +export declare const ScriptHighlightRules: FunctionConstructor; +export declare const XJsonHighlightRules: FunctionConstructor; + +export declare const XJsonMode: FunctionConstructor; + +/** + * @param otherRules Another Ace ruleset + * @param embedUnder The state name under which the rules will be embedded. Defaults to "json". + */ +export declare const addXJsonToRules: (otherRules: any, embedUnder?: string) => void; diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/index.js b/src/plugins/es_ui_shared/console_lang/ace/modes/index.js new file mode 100644 index 0000000000000..955f23116f659 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/ace/modes/index.js @@ -0,0 +1,27 @@ +/* + * 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 { + ElasticsearchSqlHighlightRules, + ScriptHighlightRules, + XJsonHighlightRules, + addXJsonToRules, +} from './lexer_rules'; + +export { XJsonMode, installXJsonMode } from './x_json'; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/elasticsearch_sql_highlight_rules.ts b/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts similarity index 100% rename from src/plugins/console/public/application/models/legacy_core_editor/mode/elasticsearch_sql_highlight_rules.ts rename to src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/elasticsearch_sql_highlight_rules.ts diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/index.js b/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/index.js new file mode 100644 index 0000000000000..be11fd726b7f2 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/index.js @@ -0,0 +1,22 @@ +/* + * 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 { ElasticsearchSqlHighlightRules } from './elasticsearch_sql_highlight_rules'; +export { ScriptHighlightRules } from './script_highlight_rules'; +export { XJsonHighlightRules, addToRules as addXJsonToRules } from './x_json_highlight_rules'; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/script_highlight_rules.js b/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/script_highlight_rules.js similarity index 100% rename from src/plugins/console/public/application/models/legacy_core_editor/mode/script_highlight_rules.js rename to src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/script_highlight_rules.js diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/x_json_highlight_rules.js b/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.js similarity index 85% rename from src/plugins/console/public/application/models/legacy_core_editor/mode/x_json_highlight_rules.js rename to src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.js index d0a79e84e809d..14323b9320330 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/x_json_highlight_rules.js +++ b/src/plugins/es_ui_shared/console_lang/ace/modes/lexer_rules/x_json_highlight_rules.js @@ -17,11 +17,16 @@ * under the License. */ -const _ = require('lodash'); +import * as _ from 'lodash'; +import ace from 'brace'; +import 'brace/mode/json'; import { ElasticsearchSqlHighlightRules } from './elasticsearch_sql_highlight_rules'; const { ScriptHighlightRules } = require('./script_highlight_rules'); +const { JsonHighlightRules } = ace.acequire('ace/mode/json_highlight_rules'); +const oop = ace.acequire('ace/lib/oop'); + const jsonRules = function(root) { root = root ? root : 'json'; const rules = {}; @@ -146,6 +151,30 @@ const jsonRules = function(root) { return rules; }; +export function XJsonHighlightRules() { + this.$rules = { + ...jsonRules('start'), + }; + + this.embedRules(ScriptHighlightRules, 'script-', [ + { + token: 'punctuation.end_triple_quote', + regex: '"""', + next: 'pop', + }, + ]); + + this.embedRules(ElasticsearchSqlHighlightRules, 'sql-', [ + { + token: 'punctuation.end_triple_quote', + regex: '"""', + next: 'pop', + }, + ]); +} + +oop.inherits(XJsonHighlightRules, JsonHighlightRules); + export function addToRules(otherRules, embedUnder) { otherRules.$rules = _.defaultsDeep(otherRules.$rules, jsonRules(embedUnder)); otherRules.embedRules(ScriptHighlightRules, 'script-', [ diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts b/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts new file mode 100644 index 0000000000000..caa7b518b8b66 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/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 { XJsonMode } from './x_json_mode'; diff --git a/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json_mode.ts b/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json_mode.ts new file mode 100644 index 0000000000000..9f804c29a5d27 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json_mode.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 ace from 'brace'; + +import { XJsonHighlightRules } from '../index'; + +const oop = ace.acequire('ace/lib/oop'); +const { Mode: JSONMode } = ace.acequire('ace/mode/json'); +const { Tokenizer: AceTokenizer } = ace.acequire('ace/tokenizer'); +const { MatchingBraceOutdent } = ace.acequire('ace/mode/matching_brace_outdent'); +const { CstyleBehaviour } = ace.acequire('ace/mode/behaviour/cstyle'); +const { FoldMode: CStyleFoldMode } = ace.acequire('ace/mode/folding/cstyle'); + +export function XJsonMode(this: any) { + const ruleset: any = new XJsonHighlightRules(); + ruleset.normalizeRules(); + this.$tokenizer = new AceTokenizer(ruleset.getRules()); + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +} + +oop.inherits(XJsonMode, JSONMode); diff --git a/src/plugins/es_ui_shared/console_lang/index.ts b/src/plugins/es_ui_shared/console_lang/index.ts new file mode 100644 index 0000000000000..a4958911af412 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/index.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +// Lib is intentionally not included in this barrel export file to separate worker logic +// from being imported with pure functions + +export { + ElasticsearchSqlHighlightRules, + ScriptHighlightRules, + XJsonHighlightRules, + addXJsonToRules, + XJsonMode, +} from './ace/modes'; diff --git a/src/plugins/es_ui_shared/console_lang/lib/index.ts b/src/plugins/es_ui_shared/console_lang/lib/index.ts new file mode 100644 index 0000000000000..bf7f0290d4158 --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/lib/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 { collapseLiteralStrings, expandLiteralStrings } from './json_xjson_translation_tools'; diff --git a/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts b/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts new file mode 100644 index 0000000000000..92c14ade791cd --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/json_xjson_translation_tools.test.ts @@ -0,0 +1,65 @@ +/* + * 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 'lodash'; +// @ts-ignore +import collapsingTests from './utils_string_collapsing.txt'; +// @ts-ignore +import expandingTests from './utils_string_expanding.txt'; + +import * as utils from '../index'; + +describe('JSON to XJSON conversion tools', () => { + it('will collapse multiline strings', () => { + const multiline = '{ "foo": """bar\nbaz""" }'; + expect(utils.collapseLiteralStrings(multiline)).toEqual('{ "foo": "bar\\nbaz" }'); + }); + + it('will collapse multiline strings with CRLF endings', () => { + const multiline = '{ "foo": """bar\r\nbaz""" }'; + expect(utils.collapseLiteralStrings(multiline)).toEqual('{ "foo": "bar\\r\\nbaz" }'); + }); +}); + +_.each(collapsingTests.split(/^=+$/m), function(fixture) { + if (fixture.trim() === '') { + return; + } + fixture = fixture.split(/^-+$/m); + const name = fixture[0].trim(); + const expanded = fixture[1].trim(); + const collapsed = fixture[2].trim(); + + test('Literal collapse - ' + name, function() { + expect(utils.collapseLiteralStrings(expanded)).toEqual(collapsed); + }); +}); + +_.each(expandingTests.split(/^=+$/m), function(fixture) { + if (fixture.trim() === '') { + return; + } + fixture = fixture.split(/^-+$/m); + const name = fixture[0].trim(); + const collapsed = fixture[1].trim(); + const expanded = fixture[2].trim(); + + test('Literal expand - ' + name, function() { + expect(utils.expandLiteralStrings(collapsed)).toEqual(expanded); + }); +}); diff --git a/src/plugins/console/public/lib/utils/__tests__/utils_string_collapsing.txt b/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt similarity index 100% rename from src/plugins/console/public/lib/utils/__tests__/utils_string_collapsing.txt rename to src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_collapsing.txt diff --git a/src/plugins/console/public/lib/utils/__tests__/utils_string_expanding.txt b/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_expanding.txt similarity index 100% rename from src/plugins/console/public/lib/utils/__tests__/utils_string_expanding.txt rename to src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/__tests__/utils_string_expanding.txt diff --git a/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/index.ts b/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/index.ts new file mode 100644 index 0000000000000..28f1aca95efab --- /dev/null +++ b/src/plugins/es_ui_shared/console_lang/lib/json_xjson_translation_tools/index.ts @@ -0,0 +1,71 @@ +/* + * 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 function collapseLiteralStrings(data: string) { + const splitData = data.split(`"""`); + for (let idx = 1; idx < splitData.length - 1; idx += 2) { + splitData[idx] = JSON.stringify(splitData[idx]); + } + return splitData.join(''); +} + +/* + The following regex describes global match on: + 1. one colon followed by any number of space characters + 2. one double quote (not escaped, special case for JSON in JSON). + 3. greedily match any non double quote and non newline char OR any escaped double quote char (non-capturing). + 4. handle a special case where an escaped slash may be the last character + 5. one double quote + + For instance: `: "some characters \" here"` + Will match and be expanded to: `"""some characters " here"""` + + */ + +const LITERAL_STRING_CANDIDATES = /((:[\s\r\n]*)([^\\])"(\\"|[^"\n])*\\?")/g; + +export function expandLiteralStrings(data: string) { + return data.replace(LITERAL_STRING_CANDIDATES, (match, string) => { + // Expand to triple quotes if there are _any_ slashes + if (string.match(/\\./)) { + const firstDoubleQuoteIdx = string.indexOf('"'); + const lastDoubleQuoteIdx = string.lastIndexOf('"'); + + // Handle a special case where we may have a value like "\"test\"". We don't + // want to expand this to """"test"""" - so we terminate before processing the string + // further if we detect this either at the start or end of the double quote section. + + if (string[firstDoubleQuoteIdx + 1] === '\\' && string[firstDoubleQuoteIdx + 2] === '"') { + return string; + } + + if (string[lastDoubleQuoteIdx - 1] === '"' && string[lastDoubleQuoteIdx - 2] === '\\') { + return string; + } + + const colonAndAnySpacing = string.slice(0, firstDoubleQuoteIdx); + const rawStringifiedValue = string.slice(firstDoubleQuoteIdx, string.length); + // Remove one level of JSON stringification + const jsonValue = JSON.parse(rawStringifiedValue); + return `${colonAndAnySpacing}"""${jsonValue}"""`; + } else { + return string; + } + }); +} diff --git a/src/plugins/es_ui_shared/public/index.ts b/src/plugins/es_ui_shared/public/index.ts index a12c951ad13a8..67e3617a85115 100644 --- a/src/plugins/es_ui_shared/public/index.ts +++ b/src/plugins/es_ui_shared/public/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export * from './components/json_editor'; +export { JsonEditor, OnJsonEditorUpdateHandler } from './components/json_editor'; diff --git a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/index.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/index.ts new file mode 100644 index 0000000000000..ae3c9962ecadb --- /dev/null +++ b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { installXJsonMode, XJsonMode } from './x_json'; diff --git a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts new file mode 100644 index 0000000000000..ae3c9962ecadb --- /dev/null +++ b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { installXJsonMode, XJsonMode } from './x_json'; diff --git a/x-pack/plugins/searchprofiler/public/application/editor/worker/index.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/index.ts similarity index 100% rename from x-pack/plugins/searchprofiler/public/application/editor/worker/index.ts rename to x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/index.ts diff --git a/x-pack/plugins/searchprofiler/public/application/editor/worker/worker.d.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.d.ts similarity index 100% rename from x-pack/plugins/searchprofiler/public/application/editor/worker/worker.d.ts rename to x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.d.ts diff --git a/x-pack/plugins/searchprofiler/public/application/editor/worker/worker.js b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.js similarity index 100% rename from x-pack/plugins/searchprofiler/public/application/editor/worker/worker.js rename to x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/worker/worker.js diff --git a/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json.ts b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json.ts new file mode 100644 index 0000000000000..bfeca045bea02 --- /dev/null +++ b/x-pack/plugins/es_ui_shared/console_lang/ace/modes/x_json/x_json.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import ace from 'brace'; +import { XJsonMode } from '../../../../../../../src/plugins/es_ui_shared/console_lang'; +import { workerModule } from './worker'; +const { WorkerClient } = ace.acequire('ace/worker/worker_client'); + +// Then clobber `createWorker` method to install our worker source. Per ace's wiki: https://github.com/ajaxorg/ace/wiki/Syntax-validation +(XJsonMode.prototype as any).createWorker = function(session: ace.IEditSession) { + const xJsonWorker = new WorkerClient(['ace'], workerModule, 'JsonWorker'); + + xJsonWorker.attachToDocument(session.getDocument()); + + xJsonWorker.on('annotate', function(e: { data: any }) { + session.setAnnotations(e.data); + }); + + xJsonWorker.on('terminate', function() { + session.clearAnnotations(); + }); + + return xJsonWorker; +}; + +export { XJsonMode }; + +export function installXJsonMode(editor: ace.Editor) { + const session = editor.getSession(); + session.setMode(new (XJsonMode as any)()); +} diff --git a/x-pack/plugins/es_ui_shared/console_lang/index.ts b/x-pack/plugins/es_ui_shared/console_lang/index.ts new file mode 100644 index 0000000000000..b5fe3a554e34d --- /dev/null +++ b/x-pack/plugins/es_ui_shared/console_lang/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { XJsonMode, installXJsonMode } from './ace/modes'; diff --git a/x-pack/plugins/es_ui_shared/console_lang/mocks.ts b/x-pack/plugins/es_ui_shared/console_lang/mocks.ts new file mode 100644 index 0000000000000..68480282ddc03 --- /dev/null +++ b/x-pack/plugins/es_ui_shared/console_lang/mocks.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +jest.mock('./ace/modes/x_json/worker', () => ({ + workerModule: { id: 'ace/mode/json_worker', src: '' }, +})); diff --git a/x-pack/plugins/searchprofiler/public/application/containers/main/main.tsx b/x-pack/plugins/searchprofiler/public/application/containers/main/main.tsx index 90617ba1c5167..aa6c20aa6a7f3 100644 --- a/x-pack/plugins/searchprofiler/public/application/containers/main/main.tsx +++ b/x-pack/plugins/searchprofiler/public/application/containers/main/main.tsx @@ -5,7 +5,6 @@ */ import React, { useCallback } from 'react'; -import _ from 'lodash'; import { EuiPage, diff --git a/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx b/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx index a70d70f117edb..ad56b3957eb74 100644 --- a/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx +++ b/x-pack/plugins/searchprofiler/public/application/editor/editor.test.tsx @@ -6,9 +6,7 @@ import 'brace'; import 'brace/mode/json'; -jest.mock('./worker', () => { - return { workerModule: { id: 'ace/mode/json_worker', src: '' } }; -}); +import '../../../../es_ui_shared/console_lang/mocks'; import { registerTestBed } from '../../../../../test_utils'; import { Editor, Props } from '.'; diff --git a/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts b/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts index e5aad16bc4af2..6f19ce12eb639 100644 --- a/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts +++ b/x-pack/plugins/searchprofiler/public/application/editor/init_editor.ts @@ -5,7 +5,7 @@ */ import ace from 'brace'; -import { installXJsonMode } from './x_json_mode'; +import { installXJsonMode } from '../../../../es_ui_shared/console_lang'; export function initializeEditor({ el, diff --git a/x-pack/plugins/searchprofiler/public/application/editor/x_json_highlight_rules.ts b/x-pack/plugins/searchprofiler/public/application/editor/x_json_highlight_rules.ts deleted file mode 100644 index 1e6e774db2e52..0000000000000 --- a/x-pack/plugins/searchprofiler/public/application/editor/x_json_highlight_rules.ts +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import ace from 'brace'; -const oop = ace.acequire('ace/lib/oop'); -const { JsonHighlightRules } = ace.acequire('ace/mode/json_highlight_rules'); -const { TextHighlightRules } = ace.acequire('ace/mode/text_highlight_rules'); - -/* - * The rules below were copied from ./src/legacy/core_plugins/console/public/src/sense_editor/mode/x_json_highlight_rules.js - * - * It is very likely that this code will move (or be removed) in future but for now - * it enables syntax highlight for extended json. - */ - -const xJsonRules = { - start: [ - { - token: [ - 'variable', - 'whitespace', - 'ace.punctuation.colon', - 'whitespace', - 'punctuation.start_triple_quote', - ], - regex: '("(?:[^"]*_)?script"|"inline"|"source")(\\s*?)(:)(\\s*?)(""")', - next: 'script-start', - merge: false, - push: true, - }, - { - token: 'variable', // single line - regex: '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)', - }, - { - token: 'punctuation.start_triple_quote', - regex: '"""', - next: 'string_literal', - merge: false, - push: true, - }, - { - token: 'string', // single line - regex: '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]', - }, - { - token: 'constant.numeric', // hex - regex: '0[xX][0-9a-fA-F]+\\b', - }, - { - token: 'constant.numeric', // float - regex: '[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b', - }, - { - token: 'constant.language.boolean', - regex: '(?:true|false)\\b', - }, - { - token: 'invalid.illegal', // single quoted strings are not allowed - regex: "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']", - }, - { - token: 'invalid.illegal', // comments are not allowed - regex: '\\/\\/.*$', - }, - { - token: 'paren.lparen', - merge: false, - regex: '{', - next: 'start', - push: true, - }, - { - token: 'paren.lparen', - merge: false, - regex: '[[(]', - }, - { - token: 'paren.rparen', - merge: false, - regex: '[\\])]', - }, - { - token: 'paren.rparen', - regex: '}', - merge: false, - next: 'pop', - }, - { - token: 'punctuation.comma', - regex: ',', - }, - { - token: 'punctuation.colon', - regex: ':', - }, - { - token: 'whitespace', - regex: '\\s+', - }, - { - token: 'text', - regex: '.+?', - }, - ], - string_literal: [ - { - token: 'punctuation.end_triple_quote', - regex: '"""', - next: 'pop', - }, - { - token: 'multi_string', - regex: '.', - }, - ], -}; - -function XJsonHighlightRules(this: any) { - this.$rules = xJsonRules; -} - -oop.inherits(XJsonHighlightRules, JsonHighlightRules); - -export function getRules() { - const ruleset: any = new (XJsonHighlightRules as any)(); - ruleset.embedRules(TextHighlightRules, 'text-', [ - { - token: 'punctuation.end_triple_quote', - regex: '"""', - next: 'pop', - }, - ]); - ruleset.normalizeRules(); - return ruleset.getRules(); -} diff --git a/x-pack/plugins/searchprofiler/public/application/editor/x_json_mode.ts b/x-pack/plugins/searchprofiler/public/application/editor/x_json_mode.ts deleted file mode 100644 index 7ac1e6105d97f..0000000000000 --- a/x-pack/plugins/searchprofiler/public/application/editor/x_json_mode.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -// Copied and modified from src/legacy/core_plugins/console/public/src/sense_editor/mode/input.js - -import ace from 'brace'; - -import * as xJsonRules from './x_json_highlight_rules'; -import { workerModule } from './worker'; - -const oop = ace.acequire('ace/lib/oop'); -const { Mode: JSONMode } = ace.acequire('ace/mode/json'); -const { Tokenizer: AceTokenizer } = ace.acequire('ace/tokenizer'); -const { MatchingBraceOutdent } = ace.acequire('ace/mode/matching_brace_outdent'); -const { CstyleBehaviour } = ace.acequire('ace/mode/behaviour/cstyle'); -const { FoldMode: CStyleFoldMode } = ace.acequire('ace/mode/folding/cstyle'); -const { WorkerClient } = ace.acequire('ace/worker/worker_client'); - -function XJsonMode(this: any) { - this.$tokenizer = new AceTokenizer(xJsonRules.getRules()); - this.$outdent = new MatchingBraceOutdent(); - this.$behaviour = new CstyleBehaviour(); - this.foldingRules = new CStyleFoldMode(); -} - -// Order here matters here: - -// 1. We first inherit -oop.inherits(XJsonMode, JSONMode); - -// 2. Then clobber `createWorker` method to install our worker source. Per ace's wiki: https://github.com/ajaxorg/ace/wiki/Syntax-validation -XJsonMode.prototype.createWorker = function(session: ace.IEditSession) { - const xJsonWorker = new WorkerClient(['ace'], workerModule, 'JsonWorker'); - - xJsonWorker.attachToDocument(session.getDocument()); - - xJsonWorker.on('annotate', function(e: { data: any }) { - session.setAnnotations(e.data); - }); - - xJsonWorker.on('terminate', function() { - session.clearAnnotations(); - }); - - return xJsonWorker; -}; - -export function installXJsonMode(editor: ace.Editor) { - const session = editor.getSession(); - session.setMode(new (XJsonMode as any)()); -} diff --git a/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts b/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts index 4267fd0d2f901..99687de0f1440 100644 --- a/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts +++ b/x-pack/plugins/searchprofiler/public/application/utils/check_for_json_errors.ts @@ -4,12 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -// Convert triple quotes into regular quotes and escape internal quotes. -function collapseLiteralStrings(data: string) { - return data.replace(/"""(?:\s*\r?\n)?((?:.|\r?\n)*?)(?:\r?\n\s*)?"""/g, function(match, literal) { - return JSON.stringify(literal); - }); -} +import { collapseLiteralStrings } from '../../../../../../src/plugins/es_ui_shared/console_lang/lib'; export function checkForParseErrors(json: string) { const sanitizedJson = collapseLiteralStrings(json); diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts index 26be3421b534e..93b8cce153d3b 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_json.test.ts @@ -3,6 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import '../../../es_ui_shared/console_lang/mocks'; + import { act } from 'react-dom/test-utils'; import { setupEnvironment, pageHelpers, nextTick, wrapBodyResponse } from './helpers'; import { WatchCreateJsonTestBed } from './helpers/watch_create_json.helpers'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx index 431eb1cae0608..943233d3c14ed 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_create_threshold.test.tsx @@ -3,6 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + +import '../../../es_ui_shared/console_lang/mocks'; + import React from 'react'; import { act } from 'react-dom/test-utils'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts index 545bfbdf7cbc2..51285a5786b00 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_edit.test.ts @@ -3,6 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import '../../../es_ui_shared/console_lang/mocks'; + import { act } from 'react-dom/test-utils'; import axiosXhrAdapter from 'axios/lib/adapters/xhr'; import axios from 'axios'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts index a0327c6dfa1db..3370e42b2417f 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_list.test.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import '../../../es_ui_shared/console_lang/mocks'; import { act } from 'react-dom/test-utils'; import * as fixtures from '../../test/fixtures'; diff --git a/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts b/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts index 973c14893f342..20b7b526705c0 100644 --- a/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts +++ b/x-pack/plugins/watcher/__jest__/client_integration/watch_status.test.ts @@ -3,6 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import '../../../es_ui_shared/console_lang/mocks'; + import { act } from 'react-dom/test-utils'; import { setupEnvironment, pageHelpers, nextTick } from './helpers'; import { WatchStatusTestBed } from './helpers/watch_status.helpers'; diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx index 91185ac604b34..b3a09d3bc0e65 100644 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx @@ -20,6 +20,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; + import { serializeJsonWatch } from '../../../../../../common/lib/serialization'; import { ErrableFormRow, SectionError, Error as ServerError } from '../../../../components'; import { onWatchSave } from '../../watch_edit_actions'; @@ -28,6 +29,8 @@ import { goToWatchList } from '../../../../lib/navigation'; import { RequestFlyout } from '../request_flyout'; import { useAppContext } from '../../../../app_context'; +import { useXJsonMode } from './use_x_json_mode'; + export const JsonWatchEditForm = () => { const { links: { putWatchApiUrl }, @@ -35,6 +38,7 @@ export const JsonWatchEditForm = () => { } = useAppContext(); const { watch, setWatchProperty } = useContext(WatchContext); + const { xJsonMode, convertToJson, setXJson, xJson } = useXJsonMode(watch.watchString); const { errors } = watch.validate(); const hasErrors = !!Object.keys(errors).find(errorKey => errors[errorKey].length >= 1); @@ -160,9 +164,9 @@ export const JsonWatchEditForm = () => { errors={jsonErrors} > { defaultMessage: 'Code editor', } )} - value={watch.watchString} - onChange={(json: string) => { + value={xJson} + onChange={(xjson: string) => { if (validationError) { setValidationError(null); } - setWatchProperty('watchString', json); + setXJson(xjson); + // Keep the watch in sync with the editor content + setWatchProperty('watchString', convertToJson(xjson)); }} /> diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx index 9ac80ade89daa..c906d05be64be 100644 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_simulate.tsx @@ -40,6 +40,8 @@ import { JsonWatchEditSimulateResults } from './json_watch_edit_simulate_results import { getTimeUnitLabel } from '../../../../lib/get_time_unit_label'; import { useAppContext } from '../../../../app_context'; +import { useXJsonMode } from './use_x_json_mode'; + const actionModeOptions = Object.keys(ACTION_MODES).map(mode => ({ text: ACTION_MODES[mode], value: ACTION_MODES[mode], @@ -94,6 +96,8 @@ export const JsonWatchEditSimulate = ({ ignoreCondition, } = executeDetails; + const { setXJson, convertToJson, xJsonMode, xJson } = useXJsonMode(alternativeInput); + const columns = [ { field: 'actionId', @@ -371,22 +375,23 @@ export const JsonWatchEditSimulate = ({ > { + value={xJson} + onChange={(xjson: string) => { + setXJson(xjson); setExecuteDetails( new ExecuteDetails({ ...executeDetails, - alternativeInput: json, + alternativeInput: convertToJson(xjson), }) ); }} diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/use_x_json_mode.ts b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/use_x_json_mode.ts new file mode 100644 index 0000000000000..7aefb0554e0e8 --- /dev/null +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/use_x_json_mode.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { useState } from 'react'; +import { XJsonMode } from '../../../../../../../es_ui_shared/console_lang'; +import { + collapseLiteralStrings, + expandLiteralStrings, +} from '../../../../../../../../../src/plugins/es_ui_shared/console_lang/lib'; + +export const xJsonMode = new XJsonMode(); + +export const useXJsonMode = (json: string) => { + const [xJson, setXJson] = useState(expandLiteralStrings(json)); + + return { + xJson, + setXJson, + xJsonMode, + convertToJson: collapseLiteralStrings, + }; +}; diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx index c1ebcdc262863..b79f9eee01834 100644 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/threshold_watch_edit/action_fields/webhook_action_fields.tsx @@ -245,7 +245,7 @@ export const WebhookActionFields: React.FunctionComponent = ({ mode="json" width="100%" height="200px" - theme="github" + theme="textmate" data-test-subj="webhookBodyEditor" aria-label={i18n.translate( 'xpack.watcher.sections.watchEdit.threshold.webhookAction.bodyCodeEditorAriaLabel', From 545240065ab323fabc708435bf535e62d238cdd8 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Mon, 17 Feb 2020 10:47:50 +0000 Subject: [PATCH 08/21] [ML] Categorization examples privilege check (#57375) * [ML] Categorization examples privilege check * adding privileges check to endpoint * fixing typo * moving privilege check to router * removing unused variable * rebasing master * removing comment Co-authored-by: Elastic Machine --- .../ml/server/models/job_service/index.js | 7 +--- .../new_job/categorization/examples.ts | 7 ++-- .../server/new_platform/job_service_schema.ts | 14 +------- .../plugins/ml/server/routes/job_service.ts | 36 +++++++++++++++++-- 4 files changed, 41 insertions(+), 23 deletions(-) diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/index.js b/x-pack/legacy/plugins/ml/server/models/job_service/index.js index 6f409e70e68b8..70b855e80a770 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/index.js +++ b/x-pack/legacy/plugins/ml/server/models/job_service/index.js @@ -8,11 +8,7 @@ import { datafeedsProvider } from './datafeeds'; import { jobsProvider } from './jobs'; import { groupsProvider } from './groups'; import { newJobCapsProvider } from './new_job_caps'; -import { - newJobChartsProvider, - categorizationExamplesProvider, - topCategoriesProvider, -} from './new_job'; +import { newJobChartsProvider, topCategoriesProvider } from './new_job'; export function jobServiceProvider(callAsCurrentUser) { return { @@ -21,7 +17,6 @@ export function jobServiceProvider(callAsCurrentUser) { ...groupsProvider(callAsCurrentUser), ...newJobCapsProvider(callAsCurrentUser), ...newJobChartsProvider(callAsCurrentUser), - ...categorizationExamplesProvider(callAsCurrentUser), ...topCategoriesProvider(callAsCurrentUser), }; } diff --git a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/examples.ts b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/examples.ts index 76473bd55db7f..ea2c71b04f56d 100644 --- a/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/examples.ts +++ b/x-pack/legacy/plugins/ml/server/models/job_service/new_job/categorization/examples.ts @@ -17,7 +17,10 @@ import { ValidationResults } from './validation_results'; const CHUNK_SIZE = 100; -export function categorizationExamplesProvider(callWithRequest: callWithRequestType) { +export function categorizationExamplesProvider( + callWithRequest: callWithRequestType, + callWithInternalUser: callWithRequestType +) { const validationResults = new ValidationResults(); async function categorizationExamples( @@ -109,7 +112,7 @@ export function categorizationExamplesProvider(callWithRequest: callWithRequestT } async function loadTokens(examples: string[], analyzer: CategorizationAnalyzer) { - const { tokens }: { tokens: Token[] } = await callWithRequest('indices.analyze', { + const { tokens }: { tokens: Token[] } = await callWithInternalUser('indices.analyze', { body: { ...getAnalyzer(analyzer), text: examples, diff --git a/x-pack/legacy/plugins/ml/server/new_platform/job_service_schema.ts b/x-pack/legacy/plugins/ml/server/new_platform/job_service_schema.ts index b37fcba737802..deb62678a777c 100644 --- a/x-pack/legacy/plugins/ml/server/new_platform/job_service_schema.ts +++ b/x-pack/legacy/plugins/ml/server/new_platform/job_service_schema.ts @@ -6,18 +6,6 @@ import { schema } from '@kbn/config-schema'; -const analyzerSchema = { - tokenizer: schema.string(), - filter: schema.maybe( - schema.arrayOf( - schema.object({ - type: schema.string(), - stopwords: schema.arrayOf(schema.maybe(schema.string())), - }) - ) - ), -}; - export const categorizationFieldExamplesSchema = { indexPatternTitle: schema.string(), query: schema.any(), @@ -26,7 +14,7 @@ export const categorizationFieldExamplesSchema = { timeField: schema.maybe(schema.string()), start: schema.number(), end: schema.number(), - analyzer: schema.object(analyzerSchema), + analyzer: schema.any(), }; export const chartSchema = { diff --git a/x-pack/legacy/plugins/ml/server/routes/job_service.ts b/x-pack/legacy/plugins/ml/server/routes/job_service.ts index 9aa3960e59e4c..5ddbd4cdfd5a5 100644 --- a/x-pack/legacy/plugins/ml/server/routes/job_service.ts +++ b/x-pack/legacy/plugins/ml/server/routes/job_service.ts @@ -4,10 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ +import Boom from 'boom'; import { schema } from '@kbn/config-schema'; +import { IScopedClusterClient } from 'src/core/server'; import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../new_platform/plugin'; +import { isSecurityDisabled } from '../lib/security_utils'; import { categorizationFieldExamplesSchema, chartSchema, @@ -21,11 +24,31 @@ import { } from '../new_platform/job_service_schema'; // @ts-ignore no declaration module import { jobServiceProvider } from '../models/job_service'; +import { categorizationExamplesProvider } from '../models/job_service/new_job'; /** * Routes for job service */ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitialization) { + async function hasPermissionToCreateJobs( + callAsCurrentUser: IScopedClusterClient['callAsCurrentUser'] + ) { + if (isSecurityDisabled(xpackMainPlugin) === true) { + return true; + } + + const resp = await callAsCurrentUser('ml.privilegeCheck', { + body: { + cluster: [ + 'cluster:admin/xpack/ml/job/put', + 'cluster:admin/xpack/ml/job/open', + 'cluster:admin/xpack/ml/datafeeds/put', + ], + }, + }); + return resp.has_all_requested; + } + /** * @apiGroup JobService * @@ -545,8 +568,17 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio }, licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { try { - const { validateCategoryExamples } = jobServiceProvider( - context.ml!.mlClient.callAsCurrentUser + // due to the use of the _analyze endpoint which is called by the kibana user, + // basic job creation privileges are required to use this endpoint + if ((await hasPermissionToCreateJobs(context.ml!.mlClient.callAsCurrentUser)) === false) { + throw Boom.forbidden( + 'Insufficient privileges, the machine_learning_admin role is required.' + ); + } + + const { validateCategoryExamples } = categorizationExamplesProvider( + context.ml!.mlClient.callAsCurrentUser, + context.ml!.mlClient.callAsInternalUser ); const { indexPatternTitle, From 54f5cc1ce384e6bcc9d431e0b60f095778ab1490 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 17 Feb 2020 11:53:42 +0100 Subject: [PATCH 09/21] [ML] Anomaly Detection: Fixes hiding date picker for settings pages. (#57544) - Fixes hiding the global date picker on anomaly detection settings pages. - Consolidates various timefilter usages for enabling/disabling the date picker into a useTimefilter() hook. --- .../application/contexts/kibana/index.ts | 1 + .../contexts/kibana/use_timefilter.test.ts | 65 +++++++++++++++++++ .../contexts/kibana/use_timefilter.ts | 38 +++++++++++ .../datavisualizer_selector.tsx | 7 +- .../file_based/file_datavisualizer.tsx | 7 +- .../datavisualizer/index_based/page.tsx | 15 ++--- .../application/routing/routes/explorer.tsx | 8 +-- .../application/routing/routes/jobs_list.tsx | 8 +-- .../application/routing/routes/overview.tsx | 2 + .../routing/routes/settings/calendar_list.tsx | 3 + .../routes/settings/calendar_new_edit.tsx | 3 + .../routing/routes/settings/filter_list.tsx | 3 + .../routes/settings/filter_list_new_edit.tsx | 3 + .../routing/routes/settings/settings.tsx | 3 + .../routes/timeseriesexplorer.test.tsx | 30 +-------- .../routing/routes/timeseriesexplorer.tsx | 10 +-- .../settings/calendars/edit/new_calendar.js | 3 - 17 files changed, 139 insertions(+), 70 deletions(-) create mode 100644 x-pack/legacy/plugins/ml/public/application/contexts/kibana/use_timefilter.test.ts create mode 100644 x-pack/legacy/plugins/ml/public/application/contexts/kibana/use_timefilter.ts diff --git a/x-pack/legacy/plugins/ml/public/application/contexts/kibana/index.ts b/x-pack/legacy/plugins/ml/public/application/contexts/kibana/index.ts index 7ebbd45fd372a..2add1b6ea161c 100644 --- a/x-pack/legacy/plugins/ml/public/application/contexts/kibana/index.ts +++ b/x-pack/legacy/plugins/ml/public/application/contexts/kibana/index.ts @@ -6,3 +6,4 @@ export { useMlKibana, StartServices, MlKibanaReactContextValue } from './kibana_context'; export { useUiSettings } from './use_ui_settings_context'; +export { useTimefilter } from './use_timefilter'; diff --git a/x-pack/legacy/plugins/ml/public/application/contexts/kibana/use_timefilter.test.ts b/x-pack/legacy/plugins/ml/public/application/contexts/kibana/use_timefilter.test.ts new file mode 100644 index 0000000000000..98ddd874c695c --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/application/contexts/kibana/use_timefilter.test.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { renderHook } from '@testing-library/react-hooks'; +import { useTimefilter } from './use_timefilter'; + +jest.mock('./kibana_context', () => ({ + useMlKibana: () => { + return { + services: { + data: { + query: { + timefilter: { + timefilter: { + disableTimeRangeSelector: jest.fn(), + disableAutoRefreshSelector: jest.fn(), + enableTimeRangeSelector: jest.fn(), + enableAutoRefreshSelector: jest.fn(), + }, + }, + }, + }, + }, + }; + }, +})); + +describe('useTimefilter', () => { + test('will not trigger any date picker settings by default', () => { + const { result } = renderHook(() => useTimefilter()); + const timefilter = result.current; + + expect(timefilter.disableTimeRangeSelector).toHaveBeenCalledTimes(0); + expect(timefilter.disableAutoRefreshSelector).toHaveBeenCalledTimes(0); + expect(timefilter.enableTimeRangeSelector).toHaveBeenCalledTimes(0); + expect(timefilter.enableTimeRangeSelector).toHaveBeenCalledTimes(0); + }); + + test('custom disabled overrides', () => { + const { result } = renderHook(() => + useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }) + ); + const timefilter = result.current; + + expect(timefilter.disableTimeRangeSelector).toHaveBeenCalledTimes(1); + expect(timefilter.disableAutoRefreshSelector).toHaveBeenCalledTimes(1); + expect(timefilter.enableTimeRangeSelector).toHaveBeenCalledTimes(0); + expect(timefilter.enableTimeRangeSelector).toHaveBeenCalledTimes(0); + }); + + test('custom enabled overrides', () => { + const { result } = renderHook(() => + useTimefilter({ timeRangeSelector: true, autoRefreshSelector: true }) + ); + const timefilter = result.current; + + expect(timefilter.disableTimeRangeSelector).toHaveBeenCalledTimes(0); + expect(timefilter.disableAutoRefreshSelector).toHaveBeenCalledTimes(0); + expect(timefilter.enableTimeRangeSelector).toHaveBeenCalledTimes(1); + expect(timefilter.enableTimeRangeSelector).toHaveBeenCalledTimes(1); + }); +}); diff --git a/x-pack/legacy/plugins/ml/public/application/contexts/kibana/use_timefilter.ts b/x-pack/legacy/plugins/ml/public/application/contexts/kibana/use_timefilter.ts new file mode 100644 index 0000000000000..374e101f63dc8 --- /dev/null +++ b/x-pack/legacy/plugins/ml/public/application/contexts/kibana/use_timefilter.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { useEffect } from 'react'; + +import { useMlKibana } from './kibana_context'; + +interface UseTimefilterOptions { + timeRangeSelector?: boolean; + autoRefreshSelector?: boolean; +} + +export const useTimefilter = ({ + timeRangeSelector, + autoRefreshSelector, +}: UseTimefilterOptions = {}) => { + const { services } = useMlKibana(); + const { timefilter } = services.data.query.timefilter; + + useEffect(() => { + if (timeRangeSelector === true) { + timefilter.enableTimeRangeSelector(); + } else if (timeRangeSelector === false) { + timefilter.disableTimeRangeSelector(); + } + + if (autoRefreshSelector === true) { + timefilter.enableAutoRefreshSelector(); + } else if (autoRefreshSelector === false) { + timefilter.disableAutoRefreshSelector(); + } + }, [timeRangeSelector, autoRefreshSelector]); + + return timefilter; +}; diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx index ae0c034f972d6..0f56f78c708ee 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/datavisualizer_selector.tsx @@ -23,7 +23,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { isFullLicense } from '../license/check_license'; -import { useMlKibana } from '../contexts/kibana'; +import { useTimefilter } from '../contexts/kibana'; import { NavigationMenu } from '../components/navigation_menu'; @@ -49,10 +49,7 @@ function startTrialDescription() { } export const DatavisualizerSelector: FC = () => { - const { services } = useMlKibana(); - const { timefilter } = services.data.query.timefilter; - timefilter.disableTimeRangeSelector(); - timefilter.disableAutoRefreshSelector(); + useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); const startTrialVisible = isFullLicense() === false; diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx index 9dcb9d25692e9..5c32d62c39f84 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx @@ -7,7 +7,7 @@ import React, { FC, Fragment } from 'react'; import { IUiSettingsClient } from 'src/core/public'; -import { useMlKibana } from '../../contexts/kibana'; +import { useTimefilter } from '../../contexts/kibana'; import { NavigationMenu } from '../../components/navigation_menu'; import { getIndexPatternsContract } from '../../util/index_utils'; @@ -19,10 +19,7 @@ export interface FileDataVisualizerPageProps { } export const FileDataVisualizerPage: FC = ({ kibanaConfig }) => { - const { services } = useMlKibana(); - const { timefilter } = services.data.query.timefilter; - timefilter.disableTimeRangeSelector(); - timefilter.disableAutoRefreshSelector(); + useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); const indexPatterns = getIndexPatternsContract(); return ( diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx index a6508ea868724..84c07651d323d 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/page.tsx @@ -38,7 +38,7 @@ import { FullTimeRangeSelector } from '../../components/full_time_range_selector import { mlTimefilterRefresh$ } from '../../services/timefilter_refresh_service'; import { useMlContext, SavedSearchQuery } from '../../contexts/ml'; import { kbnTypeToMLJobType } from '../../util/field_types_utils'; -import { useMlKibana } from '../../contexts/kibana'; +import { useTimefilter } from '../../contexts/kibana'; import { timeBasedIndexCheck, getQueryFromSavedSearch } from '../../util/index_utils'; import { TimeBuckets } from '../../util/time_buckets'; import { useUrlState } from '../../util/url_state'; @@ -97,11 +97,13 @@ function getDefaultPageState(): DataVisualizerPageState { } export const Page: FC = () => { - const { services } = useMlKibana(); const mlContext = useMlContext(); - const { timefilter } = services.data.query.timefilter; const { combinedQuery, currentIndexPattern, currentSavedSearch, kibanaConfig } = mlContext; + const timefilter = useTimefilter({ + timeRangeSelector: currentIndexPattern.timeFieldName !== undefined, + autoRefreshSelector: true, + }); const dataLoader = new DataLoader(currentIndexPattern, kibanaConfig); const [globalState, setGlobalState] = useUrlState('_g'); @@ -122,13 +124,6 @@ export const Page: FC = () => { const [lastRefresh, setLastRefresh] = useState(0); useEffect(() => { - if (currentIndexPattern.timeFieldName !== undefined) { - timefilter.enableTimeRangeSelector(); - } else { - timefilter.disableTimeRangeSelector(); - } - - timefilter.enableAutoRefreshSelector(); timeBasedIndexCheck(currentIndexPattern, true); }, []); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx index b0046f7b8d699..2c6726338d2f1 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx @@ -29,7 +29,7 @@ import { useTableInterval } from '../../components/controls/select_interval'; import { useTableSeverity } from '../../components/controls/select_severity'; import { useUrlState } from '../../util/url_state'; import { ANOMALY_DETECTION_BREADCRUMB, ML_BREADCRUMB } from '../breadcrumbs'; -import { useMlKibana } from '../../contexts/kibana'; +import { useTimefilter } from '../../contexts/kibana'; const breadcrumbs = [ ML_BREADCRUMB, @@ -70,8 +70,7 @@ const ExplorerUrlStateManager: FC = ({ jobsWithTim const [appState, setAppState] = useUrlState('_a'); const [globalState, setGlobalState] = useUrlState('_g'); const [lastRefresh, setLastRefresh] = useState(0); - const { services } = useMlKibana(); - const { timefilter } = services.data.query.timefilter; + const timefilter = useTimefilter({ timeRangeSelector: true, autoRefreshSelector: true }); const { jobIds } = useJobSelection(jobsWithTimeRange, getDateFormatTz()); @@ -111,9 +110,6 @@ const ExplorerUrlStateManager: FC = ({ jobsWithTim }, [globalState?.time?.from, globalState?.time?.to]); useEffect(() => { - timefilter.enableTimeRangeSelector(); - timefilter.enableAutoRefreshSelector(); - const viewByFieldName = appState?.mlExplorerSwimlane?.viewByFieldName; if (viewByFieldName !== undefined) { explorerService.setViewBySwimlaneFieldName(viewByFieldName); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/jobs_list.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/jobs_list.tsx index ca2c0750397e5..c1d686d356dda 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/jobs_list.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/jobs_list.tsx @@ -14,8 +14,8 @@ import { MlRoute, PageLoader, PageProps } from '../router'; import { useResolver } from '../use_resolver'; import { basicResolvers } from '../resolvers'; import { JobsPage } from '../../jobs/jobs_list'; +import { useTimefilter } from '../../contexts/kibana'; import { ANOMALY_DETECTION_BREADCRUMB, ML_BREADCRUMB } from '../breadcrumbs'; -import { useMlKibana } from '../../contexts/kibana'; const breadcrumbs = [ ML_BREADCRUMB, @@ -36,8 +36,7 @@ export const jobListRoute: MlRoute = { const PageWrapper: FC = ({ deps }) => { const { context } = useResolver(undefined, undefined, deps.config, basicResolvers(deps)); - const { services } = useMlKibana(); - const { timefilter } = services.data.query.timefilter; + const timefilter = useTimefilter({ timeRangeSelector: false, autoRefreshSelector: true }); const [globalState, setGlobalState] = useUrlState('_g'); @@ -48,9 +47,6 @@ const PageWrapper: FC = ({ deps }) => { const blockRefresh = refreshValue === 0 || refreshPause === true; useEffect(() => { - timefilter.disableTimeRangeSelector(); - timefilter.enableAutoRefreshSelector(); - // If the refreshInterval defaults to 0s/pause=true, set it to 30s/pause=false, // otherwise pass on the globalState's settings to the date picker. const refreshInterval = diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/overview.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/overview.tsx index 85227c11582d9..b1e00158efb94 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/overview.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/overview.tsx @@ -16,6 +16,7 @@ import { checkFullLicense } from '../../license/check_license'; import { checkGetJobsPrivilege } from '../../privilege/check_privilege'; import { getMlNodeCount } from '../../ml_nodes_check'; import { loadMlServerInfo } from '../../services/ml_server_info'; +import { useTimefilter } from '../../contexts/kibana'; import { ML_BREADCRUMB } from '../breadcrumbs'; const breadcrumbs = [ @@ -41,6 +42,7 @@ const PageWrapper: FC = ({ deps }) => { getMlNodeCount, loadMlServerInfo, }); + useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); return ( diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_list.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_list.tsx index fdbfcb3397c75..c1bfaa2fe6c1e 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_list.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_list.tsx @@ -15,6 +15,7 @@ import { i18n } from '@kbn/i18n'; import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; +import { useTimefilter } from '../../../contexts/kibana'; import { checkFullLicense } from '../../../license/check_license'; import { checkGetJobsPrivilege, checkPermission } from '../../../privilege/check_privilege'; import { getMlNodeCount } from '../../../ml_nodes_check/check_ml_nodes'; @@ -45,6 +46,8 @@ const PageWrapper: FC = ({ deps }) => { getMlNodeCount, }); + useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); + const canCreateCalendar = checkPermission('canCreateCalendar'); const canDeleteCalendar = checkPermission('canDeleteCalendar'); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx index 7f622a1bba62b..7af2e49e3a69e 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/calendar_new_edit.tsx @@ -15,6 +15,7 @@ import { i18n } from '@kbn/i18n'; import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; +import { useTimefilter } from '../../../contexts/kibana'; import { checkFullLicense } from '../../../license/check_license'; import { checkGetJobsPrivilege, checkPermission } from '../../../privilege/check_privilege'; import { checkMlNodesAvailable } from '../../../ml_nodes_check/check_ml_nodes'; @@ -77,6 +78,8 @@ const PageWrapper: FC = ({ location, mode, deps }) => { checkMlNodesAvailable, }); + useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); + const canCreateCalendar = checkPermission('canCreateCalendar'); const canDeleteCalendar = checkPermission('canDeleteCalendar'); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list.tsx index 6a4ce271bff17..9c5c06b76247c 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list.tsx @@ -15,6 +15,7 @@ import { i18n } from '@kbn/i18n'; import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; +import { useTimefilter } from '../../../contexts/kibana'; import { checkFullLicense } from '../../../license/check_license'; import { checkGetJobsPrivilege, checkPermission } from '../../../privilege/check_privilege'; import { getMlNodeCount } from '../../../ml_nodes_check/check_ml_nodes'; @@ -46,6 +47,8 @@ const PageWrapper: FC = ({ deps }) => { getMlNodeCount, }); + useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); + const canCreateFilter = checkPermission('canCreateFilter'); const canDeleteFilter = checkPermission('canDeleteFilter'); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx index 4fa15ebaac21a..752b889490e58 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/filter_list_new_edit.tsx @@ -15,6 +15,7 @@ import { i18n } from '@kbn/i18n'; import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; +import { useTimefilter } from '../../../contexts/kibana'; import { checkFullLicense } from '../../../license/check_license'; import { checkGetJobsPrivilege, checkPermission } from '../../../privilege/check_privilege'; import { checkMlNodesAvailable } from '../../../ml_nodes_check/check_ml_nodes'; @@ -77,6 +78,8 @@ const PageWrapper: FC = ({ location, mode, deps }) => { checkMlNodesAvailable, }); + useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); + const canCreateFilter = checkPermission('canCreateFilter'); const canDeleteFilter = checkPermission('canDeleteFilter'); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/settings.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/settings.tsx index 846512503ede5..10efb2dcc60c7 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/settings.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/settings/settings.tsx @@ -14,6 +14,7 @@ import React, { FC } from 'react'; import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; +import { useTimefilter } from '../../../contexts/kibana'; import { checkFullLicense } from '../../../license/check_license'; import { checkGetJobsPrivilege, checkPermission } from '../../../privilege/check_privilege'; import { getMlNodeCount } from '../../../ml_nodes_check/check_ml_nodes'; @@ -35,6 +36,8 @@ const PageWrapper: FC = ({ deps }) => { getMlNodeCount, }); + useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); + const canGetFilters = checkPermission('canGetFilters'); const canGetCalendars = checkPermission('canGetCalendars'); diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.test.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.test.tsx index 0ae42aa44e089..8633947374a8b 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.test.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.test.tsx @@ -12,33 +12,7 @@ import { I18nProvider } from '@kbn/i18n/react'; import { TimeSeriesExplorerUrlStateManager } from './timeseriesexplorer'; -jest.mock('ui/new_platform', () => ({ - npStart: { - plugins: { - data: { - query: { - timefilter: { - timefilter: { - enableTimeRangeSelector: jest.fn(), - enableAutoRefreshSelector: jest.fn(), - getRefreshInterval: jest.fn(), - setRefreshInterval: jest.fn(), - getTime: jest.fn(), - isAutoRefreshSelectorEnabled: jest.fn(), - isTimeRangeSelectorEnabled: jest.fn(), - getRefreshIntervalUpdate$: jest.fn(), - getTimeUpdate$: jest.fn(), - getEnabledUpdated$: jest.fn(), - }, - history: { get: jest.fn() }, - }, - }, - }, - }, - }, -})); - -jest.mock('../../contexts/kibana', () => ({ +jest.mock('../../contexts/kibana/kibana_context', () => ({ useMlKibana: () => { return { services: { @@ -47,6 +21,8 @@ jest.mock('../../contexts/kibana', () => ({ query: { timefilter: { timefilter: { + disableTimeRangeSelector: jest.fn(), + disableAutoRefreshSelector: jest.fn(), enableTimeRangeSelector: jest.fn(), enableAutoRefreshSelector: jest.fn(), getRefreshInterval: jest.fn(), diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx index 5bc2435db078c..f8a6f6c454fc0 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx @@ -35,7 +35,7 @@ import { useRefresh } from '../use_refresh'; import { useResolver } from '../use_resolver'; import { basicResolvers } from '../resolvers'; import { ANOMALY_DETECTION_BREADCRUMB, ML_BREADCRUMB } from '../breadcrumbs'; -import { useMlKibana } from '../../contexts/kibana'; +import { useTimefilter } from '../../contexts/kibana'; export const timeSeriesExplorerRoute: MlRoute = { path: '/timeseriesexplorer', @@ -88,8 +88,7 @@ export const TimeSeriesExplorerUrlStateManager: FC(); - const { services } = useMlKibana(); - const { timefilter } = services.data.query.timefilter; + const timefilter = useTimefilter({ timeRangeSelector: true, autoRefreshSelector: true }); const refresh = useRefresh(); useEffect(() => { @@ -106,11 +105,6 @@ export const TimeSeriesExplorerUrlStateManager: FC { - timefilter.enableTimeRangeSelector(); - timefilter.enableAutoRefreshSelector(); - }, []); - // We cannot simply infer bounds from the globalState's `time` attribute // with `moment` since it can contain custom strings such as `now-15m`. // So when globalState's `time` changes, we update the timefilter and use diff --git a/x-pack/legacy/plugins/ml/public/application/settings/calendars/edit/new_calendar.js b/x-pack/legacy/plugins/ml/public/application/settings/calendars/edit/new_calendar.js index 0489528fa0f63..935e67ec05eff 100644 --- a/x-pack/legacy/plugins/ml/public/application/settings/calendars/edit/new_calendar.js +++ b/x-pack/legacy/plugins/ml/public/application/settings/calendars/edit/new_calendar.js @@ -50,9 +50,6 @@ class NewCalendarUI extends Component { } componentDidMount() { - const { timefilter } = this.props.kibana.services.data.query.timefilter; - timefilter.disableTimeRangeSelector(); - timefilter.disableAutoRefreshSelector(); this.formSetup(); } From 5c7af8656fea9642d70d9e3c6a4b8699a9969d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Mon, 17 Feb 2020 11:21:01 +0000 Subject: [PATCH 10/21] [Telemetry] Fix bug introduced in #55859 (#57441) * [Telemetry] Refactor to TS Monitoring telemetry_collection files * [Telemetry] Fetch side documents generated by monitoring to build up the Kibana plugins stats * Update x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_beats_stats.ts Co-Authored-By: Ahmad Bamieh * Fix import in test file * Move mocha tests to Jest + TS * Fix extended telemetry in functional tests * Fix types * [Telemetry] Fix bug in usage_collector wrong function override * Revert integration tests (change not needed) Co-authored-by: Ahmad Bamieh Co-authored-by: Elastic Machine --- .../telemetry/server/collection_manager.ts | 6 +- .../server/collector/collector.ts | 2 +- .../server/collector/usage_collector.ts | 6 +- .../fixtures/beats_stats_results.json | 0 .../create_query.js => create_query.test.ts} | 11 +- .../{create_query.js => create_query.ts} | 22 +- ...get_all_stats.js => get_all_stats.test.ts} | 58 +++-- .../{get_all_stats.js => get_all_stats.ts} | 60 +++-- ...beats_stats.js => get_beats_stats.test.ts} | 52 ++--- ...{get_beats_stats.js => get_beats_stats.ts} | 206 ++++++++++++++---- ...ter_uuids.js => get_cluster_uuids.test.ts} | 21 +- .../get_es_stats.js => get_es_stats.test.ts} | 21 +- .../{get_es_stats.js => get_es_stats.ts} | 33 ++- ..._stats.js => get_high_level_stats.test.ts} | 27 ++- ...level_stats.js => get_high_level_stats.ts} | 148 ++++++++++--- ...bana_stats.js => get_kibana_stats.test.ts} | 164 ++++++++------ ...et_kibana_stats.js => get_kibana_stats.ts} | 117 +++++++--- .../register_monitoring_collection.ts | 1 - 18 files changed, 673 insertions(+), 282 deletions(-) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{__tests__ => __mocks__}/fixtures/beats_stats_results.json (100%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{__tests__/create_query.js => create_query.test.ts} (89%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{create_query.js => create_query.ts} (80%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{__tests__/get_all_stats.js => get_all_stats.test.ts} (78%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{get_all_stats.js => get_all_stats.ts} (66%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{__tests__/get_beats_stats.js => get_beats_stats.test.ts} (75%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{get_beats_stats.js => get_beats_stats.ts} (60%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{__tests__/get_cluster_uuids.js => get_cluster_uuids.test.ts} (77%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{__tests__/get_es_stats.js => get_es_stats.test.ts} (82%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{get_es_stats.js => get_es_stats.ts} (71%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{__tests__/get_high_level_stats.js => get_high_level_stats.test.ts} (91%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{get_high_level_stats.js => get_high_level_stats.ts} (66%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{__tests__/get_kibana_stats.js => get_kibana_stats.test.ts} (79%) rename x-pack/legacy/plugins/monitoring/server/telemetry_collection/{get_kibana_stats.js => get_kibana_stats.ts} (58%) diff --git a/src/legacy/core_plugins/telemetry/server/collection_manager.ts b/src/legacy/core_plugins/telemetry/server/collection_manager.ts index 933c249cd7279..0394dea343adf 100644 --- a/src/legacy/core_plugins/telemetry/server/collection_manager.ts +++ b/src/legacy/core_plugins/telemetry/server/collection_manager.ts @@ -41,8 +41,8 @@ export interface StatsCollectionConfig { usageCollection: UsageCollectionSetup; callCluster: CallCluster; server: any; - start: string; - end: string; + start: string | number; + end: string | number; } export type StatsGetterConfig = UnencryptedStatsGetterConfig | EncryptedStatsGetterConfig; @@ -193,7 +193,7 @@ export class TelemetryCollectionManager { } } catch (err) { statsCollectionConfig.server.log( - ['debu', 'telemetry', 'collection'], + ['debug', 'telemetry', 'collection'], `Failed to collect any usage with registered collections.` ); // swallow error to try next collection; diff --git a/src/plugins/usage_collection/server/collector/collector.ts b/src/plugins/usage_collection/server/collector/collector.ts index e102dc2a64ee8..91951aa2f3edf 100644 --- a/src/plugins/usage_collection/server/collector/collector.ts +++ b/src/plugins/usage_collection/server/collector/collector.ts @@ -85,7 +85,7 @@ export class Collector { protected defaultFormatterForBulkUpload(result: T) { return { type: this.type, - payload: result, + payload: (result as unknown) as U, }; } } diff --git a/src/plugins/usage_collection/server/collector/usage_collector.ts b/src/plugins/usage_collection/server/collector/usage_collector.ts index 05c701bd3abf4..bf861a94fccff 100644 --- a/src/plugins/usage_collection/server/collector/usage_collector.ts +++ b/src/plugins/usage_collection/server/collector/usage_collector.ts @@ -24,14 +24,14 @@ export class UsageCollector ex T, U > { - protected defaultUsageFormatterForBulkUpload(result: T) { + protected defaultFormatterForBulkUpload(result: T) { return { type: KIBANA_STATS_TYPE, - payload: { + payload: ({ usage: { [this.type]: result, }, - }, + } as unknown) as U, }; } } diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/fixtures/beats_stats_results.json b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__mocks__/fixtures/beats_stats_results.json similarity index 100% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/fixtures/beats_stats_results.json rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/__mocks__/fixtures/beats_stats_results.json diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/create_query.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/create_query.test.ts similarity index 89% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/create_query.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/create_query.test.ts index 63c779ab4b520..a85d084f83d83 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/create_query.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/create_query.test.ts @@ -4,14 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; import { set } from 'lodash'; -import { createTypeFilter, createQuery } from '../create_query.js'; +import { createTypeFilter, createQuery } from './create_query'; describe('Create Type Filter', () => { it('Builds a type filter syntax', () => { const typeFilter = createTypeFilter('my_type'); - expect(typeFilter).to.eql({ + expect(typeFilter).toStrictEqual({ bool: { should: [{ term: { _type: 'my_type' } }, { term: { type: 'my_type' } }] }, }); }); @@ -36,7 +35,7 @@ describe('Create Query', () => { ], }, }; - expect(result).to.be.eql(expected); + expect(result).toStrictEqual(expected); }); it('Uses `type` option to add type filter with minimal fields', () => { @@ -47,7 +46,7 @@ describe('Create Query', () => { { term: { _type: 'test-type-yay' } }, { term: { type: 'test-type-yay' } }, ]); - expect(result).to.be.eql(expected); + expect(result).toStrictEqual(expected); }); it('Uses `type` option to add type filter with all other option fields', () => { @@ -77,6 +76,6 @@ describe('Create Query', () => { ], }, }; - expect(result).to.be.eql(expected); + expect(result).toStrictEqual(expected); }); }); diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/create_query.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/create_query.ts similarity index 80% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/create_query.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/create_query.ts index 6fcbb677b307d..9a801094458bd 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/create_query.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/create_query.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { defaults } from 'lodash'; import moment from 'moment'; /* @@ -14,7 +13,7 @@ import moment from 'moment'; * TODO: this backwards compatibility helper will only be supported for 5.x-6. This * function should be removed in 7.0 */ -export const createTypeFilter = type => { +export const createTypeFilter = (type: string) => { return { bool: { should: [{ term: { _type: type } }, { term: { type } }], @@ -22,6 +21,18 @@ export const createTypeFilter = type => { }; }; +export interface QueryOptions { + type?: string; + filters?: object[]; + clusterUuid?: string; + start?: string | number; + end?: string | number; +} + +interface RangeFilter { + range: { [key: string]: { format?: string; gte?: string | number; lte?: string | number } }; +} + /* * Creates the boilerplace for querying monitoring data, including filling in * start time and end time, and injecting additional filters. @@ -36,9 +47,8 @@ export const createTypeFilter = type => { * @param {Date} options.start - numeric timestamp (optional) * @param {Date} options.end - numeric timestamp (optional) */ -export function createQuery(options) { - options = defaults(options, { filters: [] }); - const { type, clusterUuid, start, end, filters } = options; +export function createQuery(options: QueryOptions) { + const { type, clusterUuid, start, end, filters = [] } = options; let typeFilter; if (type) { @@ -50,7 +60,7 @@ export function createQuery(options) { clusterUuidFilter = { term: { cluster_uuid: clusterUuid } }; } - let timeRangeFilter; + let timeRangeFilter: RangeFilter | undefined; if (start || end) { timeRangeFilter = { range: { diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_all_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.test.ts similarity index 78% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_all_stats.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.test.ts index f27fde50242f4..470642f9dd8a3 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_all_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.test.ts @@ -4,12 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; import sinon from 'sinon'; -import { addStackStats, getAllStats, handleAllStats } from '../get_all_stats'; +import { addStackStats, getAllStats, handleAllStats } from './get_all_stats'; +import { ESClusterStats } from './get_es_stats'; +import { KibanaStats } from './get_kibana_stats'; +import { ClustersHighLevelStats } from './get_high_level_stats'; -// FAILING: https://github.com/elastic/kibana/issues/51371 -describe.skip('get_all_stats', () => { +describe('get_all_stats', () => { const size = 123; const start = 0; const end = 1; @@ -100,9 +101,6 @@ describe.skip('get_all_stats', () => { describe('getAllStats', () => { it('returns clusters', async () => { - const clusterUuidsResponse = { - aggregations: { cluster_uuids: { buckets: [{ key: 'a' }] } }, - }; const esStatsResponse = { hits: { hits: [{ _id: 'a', _source: { cluster_uuid: 'a' } }], @@ -177,15 +175,25 @@ describe.skip('get_all_stats', () => { callCluster .withArgs('search') .onCall(0) - .returns(Promise.resolve(clusterUuidsResponse)) - .onCall(1) .returns(Promise.resolve(esStatsResponse)) - .onCall(2) + .onCall(1) .returns(Promise.resolve(kibanaStatsResponse)) + .onCall(2) + .returns(Promise.resolve(logstashStatsResponse)) .onCall(3) - .returns(Promise.resolve(logstashStatsResponse)); + .returns(Promise.resolve({})) // Beats stats + .onCall(4) + .returns(Promise.resolve({})); // Beats state - expect(await getAllStats({ callCluster, server, start, end })).to.eql(allClusters); + expect( + await getAllStats([{ clusterUuid: 'a' }], { + callCluster: callCluster as any, + usageCollection: {} as any, + server, + start, + end, + }) + ).toStrictEqual(allClusters); }); it('returns empty clusters', async () => { @@ -195,21 +203,33 @@ describe.skip('get_all_stats', () => { callCluster.withArgs('search').returns(Promise.resolve(clusterUuidsResponse)); - expect(await getAllStats({ callCluster, server, start, end })).to.eql([]); + expect( + await getAllStats([], { + callCluster: callCluster as any, + usageCollection: {} as any, + server, + start, + end, + }) + ).toStrictEqual([]); }); }); describe('handleAllStats', () => { it('handles response', () => { - const clusters = handleAllStats(esClusters, { kibana: kibanaStats, logstash: logstashStats }); + const clusters = handleAllStats(esClusters as ESClusterStats[], { + kibana: (kibanaStats as unknown) as KibanaStats, + logstash: (logstashStats as unknown) as ClustersHighLevelStats, + beats: {}, + }); - expect(clusters).to.eql(expectedClusters); + expect(clusters).toStrictEqual(expectedClusters); }); it('handles no clusters response', () => { - const clusters = handleAllStats([], {}); + const clusters = handleAllStats([], {} as any); - expect(clusters).to.have.length(0); + expect(clusters).toHaveLength(0); }); }); @@ -230,9 +250,9 @@ describe.skip('get_all_stats', () => { }, }; - addStackStats(cluster, stats, 'xyz'); + addStackStats(cluster as ESClusterStats, stats, 'xyz'); - expect(cluster.stack_stats.xyz).to.be(stats.a); + expect((cluster as any).stack_stats.xyz).toStrictEqual(stats.a); }); }); }); diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.ts similarity index 66% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.ts index 87281a19141ae..aa5e937387daf 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_all_stats.ts @@ -6,22 +6,26 @@ import { get, set, merge } from 'lodash'; +import { StatsGetter } from 'src/legacy/core_plugins/telemetry/server/collection_manager'; import { LOGSTASH_SYSTEM_ID, KIBANA_SYSTEM_ID, BEATS_SYSTEM_ID } from '../../common/constants'; -import { getElasticsearchStats } from './get_es_stats'; -import { getKibanaStats } from './get_kibana_stats'; +import { getElasticsearchStats, ESClusterStats } from './get_es_stats'; +import { getKibanaStats, KibanaStats } from './get_kibana_stats'; import { getBeatsStats } from './get_beats_stats'; import { getHighLevelStats } from './get_high_level_stats'; +type PromiseReturnType any> = ReturnType extends Promise + ? R + : T; + /** * Get statistics for all products joined by Elasticsearch cluster. + * Returns the array of clusters joined with the Kibana and Logstash instances. * - * @param {Object} server The Kibana server instance used to call ES as the internal user - * @param {function} callCluster The callWithRequest or callWithInternalUser handler - * @param {Date} start The starting range to request data - * @param {Date} end The ending range to request data - * @return {Promise} The array of clusters joined with the Kibana and Logstash instances. */ -export async function getAllStats(clustersDetails, { server, callCluster, start, end }) { +export const getAllStats: StatsGetter = async ( + clustersDetails, + { server, callCluster, start, end } +) => { const clusterUuids = clustersDetails.map(clusterDetails => clusterDetails.clusterUuid); const [esClusters, kibana, logstash, beats] = await Promise.all([ @@ -32,7 +36,7 @@ export async function getAllStats(clustersDetails, { server, callCluster, start, ]); return handleAllStats(esClusters, { kibana, logstash, beats }); -} +}; /** * Combine the statistics from the stack to create "cluster" stats that associate all products together based on the cluster @@ -41,9 +45,21 @@ export async function getAllStats(clustersDetails, { server, callCluster, start, * @param {Array} clusters The Elasticsearch clusters * @param {Object} kibana The Kibana instances keyed by Cluster UUID * @param {Object} logstash The Logstash nodes keyed by Cluster UUID - * @return {Array} The clusters joined with the Kibana and Logstash instances under each cluster's {@code stack_stats}. + * + * Returns the clusters joined with the Kibana and Logstash instances under each cluster's {@code stack_stats}. */ -export function handleAllStats(clusters, { kibana, logstash, beats }) { +export function handleAllStats( + clusters: ESClusterStats[], + { + kibana, + logstash, + beats, + }: { + kibana: KibanaStats; + logstash: PromiseReturnType; + beats: PromiseReturnType; + } +) { return clusters.map(cluster => { // if they are using Kibana or Logstash, then add it to the cluster details under cluster.stack_stats addStackStats(cluster, kibana, KIBANA_SYSTEM_ID); @@ -62,8 +78,12 @@ export function handleAllStats(clusters, { kibana, logstash, beats }) { * @param {Object} allProductStats Product stats, keyed by Cluster UUID * @param {String} product The product name being added (e.g., 'kibana' or 'logstash') */ -export function addStackStats(cluster, allProductStats, product) { - const productStats = get(allProductStats, cluster.cluster_uuid); +export function addStackStats( + cluster: ESClusterStats & { stack_stats?: { [product: string]: K } }, + allProductStats: T, + product: string +) { + const productStats = allProductStats[cluster.cluster_uuid]; // Don't add it if they're not using (or configured to report stats) this product for this cluster if (productStats) { @@ -75,12 +95,20 @@ export function addStackStats(cluster, allProductStats, product) { } } -export function mergeXPackStats(cluster, allProductStats, path, product) { +export function mergeXPackStats( + cluster: ESClusterStats & { stack_stats?: { xpack?: { [product: string]: unknown } } }, + allProductStats: T, + path: string, + product: string +) { const productStats = get(allProductStats, cluster.cluster_uuid + '.' + path); if (productStats || productStats === 0) { - if (!get(cluster, 'stack_stats.xpack')) { - set(cluster, 'stack_stats.xpack', {}); + if (!cluster.stack_stats) { + cluster.stack_stats = {}; + } + if (!cluster.stack_stats.xpack) { + cluster.stack_stats.xpack = {}; } const mergeStats = {}; diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_beats_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_beats_stats.test.ts similarity index 75% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_beats_stats.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_beats_stats.test.ts index 522be71555fba..30888e1af3f53 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_beats_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_beats_stats.test.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { fetchBeatsStats, processResults } from '../get_beats_stats'; +import { fetchBeatsStats, processResults } from './get_beats_stats'; import sinon from 'sinon'; -import expect from '@kbn/expect'; -import beatsStatsResultSet from './fixtures/beats_stats_results'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const beatsStatsResultSet = require('./__mocks__/fixtures/beats_stats_results'); const getBaseOptions = () => ({ clusters: {}, @@ -22,8 +22,8 @@ describe('Get Beats Stats', () => { const clusterUuids = ['aCluster', 'bCluster', 'cCluster']; const start = 100; const end = 200; - let server; - let callCluster; + let server = { config: () => ({ get: sinon.stub() }) }; + let callCluster = sinon.stub(); beforeEach(() => { const getStub = { get: sinon.stub() }; @@ -32,34 +32,34 @@ describe('Get Beats Stats', () => { callCluster = sinon.stub(); }); - it('should set `from: 0, to: 10000` in the query', () => { - fetchBeatsStats(server, callCluster, clusterUuids, start, end); + it('should set `from: 0, to: 10000` in the query', async () => { + await fetchBeatsStats(server, callCluster, clusterUuids, start, end, {} as any); const { args } = callCluster.firstCall; const [api, { body }] = args; - expect(api).to.be('search'); - expect(body.from).to.be(0); - expect(body.size).to.be(10000); + expect(api).toEqual('search'); + expect(body.from).toEqual(0); + expect(body.size).toEqual(10000); }); - it('should set `from: 10000, from: 10000` in the query', () => { - fetchBeatsStats(server, callCluster, clusterUuids, start, end, { page: 1 }); + it('should set `from: 10000, from: 10000` in the query', async () => { + await fetchBeatsStats(server, callCluster, clusterUuids, start, end, { page: 1 } as any); const { args } = callCluster.firstCall; const [api, { body }] = args; - expect(api).to.be('search'); - expect(body.from).to.be(10000); - expect(body.size).to.be(10000); + expect(api).toEqual('search'); + expect(body.from).toEqual(10000); + expect(body.size).toEqual(10000); }); - it('should set `from: 20000, from: 10000` in the query', () => { - fetchBeatsStats(server, callCluster, clusterUuids, start, end, { page: 2 }); + it('should set `from: 20000, from: 10000` in the query', async () => { + await fetchBeatsStats(server, callCluster, clusterUuids, start, end, { page: 2 } as any); const { args } = callCluster.firstCall; const [api, { body }] = args; - expect(api).to.be('search'); - expect(body.from).to.be(20000); - expect(body.size).to.be(10000); + expect(api).toEqual('search'); + expect(body.from).toEqual(20000); + expect(body.size).toEqual(10000); }); }); @@ -68,9 +68,9 @@ describe('Get Beats Stats', () => { const resultsEmpty = undefined; const options = getBaseOptions(); - processResults(resultsEmpty, options); + processResults(resultsEmpty as any, options); - expect(options.clusters).to.eql({}); + expect(options.clusters).toStrictEqual({}); }); it('should summarize single result with some missing fields', () => { @@ -92,9 +92,9 @@ describe('Get Beats Stats', () => { }; const options = getBaseOptions(); - processResults(results, options); + processResults(results as any, options); - expect(options.clusters).to.eql({ + expect(options.clusters).toStrictEqual({ FlV4ckTxQ0a78hmBkzzc9A: { count: 1, versions: {}, @@ -122,11 +122,11 @@ describe('Get Beats Stats', () => { const options = getBaseOptions(); // beatsStatsResultSet is an array of many small query results - beatsStatsResultSet.forEach(results => { + beatsStatsResultSet.forEach((results: any) => { processResults(results, options); }); - expect(options.clusters).to.eql({ + expect(options.clusters).toStrictEqual({ W7hppdX7R229Oy3KQbZrTw: { count: 5, versions: { '7.0.0-alpha1': 5 }, diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_beats_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_beats_stats.ts similarity index 60% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_beats_stats.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_beats_stats.ts index 5722228b60207..975a3bfee6333 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_beats_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_beats_stats.ts @@ -5,6 +5,8 @@ */ import { get } from 'lodash'; +import { StatsCollectionConfig } from 'src/legacy/core_plugins/telemetry/server/collection_manager'; +import { SearchResponse } from 'elasticsearch'; import { createQuery } from './create_query'; import { INDEX_PATTERN_BEATS } from '../../common/constants'; @@ -33,6 +35,107 @@ const getBaseStats = () => ({ }, }); +export interface BeatsStats { + cluster_uuid: string; + beats_stats?: { + beat?: { + version?: string; + type?: string; + host?: string; + }; + metrics?: { + libbeat?: { + output?: { + type?: string; + }; + pipeline?: { + events?: { + published?: number; + }; + }; + }; + }; + }; + beats_state?: { + beat?: { + type?: string; + }; + state?: { + input?: { + names: string[]; + count: number; + }; + module?: { + names: string[]; + count: number; + }; + heartbeat?: HeartbeatBase; + functionbeat?: { + functions?: { + count?: number; + }; + }; + host?: { + architecture: string; + os: { platform: string }; + }; + }; + }; +} + +interface HeartbeatBase { + monitors: number; + endpoints: number; + // I have to add the '| number' bit because otherwise TS complains about 'monitors' and 'endpoints' not being of type HeartbeatBase + [key: string]: HeartbeatBase | number | undefined; +} + +export interface BeatsBaseStats { + // stats + versions: { [version: string]: number }; + types: { [type: string]: number }; + outputs: { [outputType: string]: number }; + count: number; + eventsPublished: number; + hosts: number; + // state + input: { + count: number; + names: string[]; + }; + module: { + count: number; + names: string[]; + }; + architecture: { + count: number; + architectures: BeatsArchitecture[]; + }; + heartbeat?: HeartbeatBase; + functionbeat?: { + functions: { + count: number; + }; + }; +} + +export interface BeatsProcessOptions { + clusters: { [clusterUuid: string]: BeatsBaseStats }; // the result object to be built up + clusterHostSets: { [clusterUuid: string]: Set }; // passed to processResults for tracking state in the results generation + clusterInputSets: { [clusterUuid: string]: Set }; // passed to processResults for tracking state in the results generation + clusterModuleSets: { [clusterUuid: string]: Set }; // passed to processResults for tracking state in the results generation + clusterArchitectureMaps: { + // passed to processResults for tracking state in the results generation + [clusterUuid: string]: Map; + }; +} + +export interface BeatsArchitecture { + name: string; + architecture: string; + count: number; +} + /* * Update a clusters object with processed beat stats * @param {Array} results - array of Beats docs from ES @@ -41,12 +144,18 @@ const getBaseStats = () => ({ * @param {Object} clusterModuleSets - the object keyed by cluster UUIDs to count the unique modules */ export function processResults( - results = [], - { clusters, clusterHostSets, clusterInputSets, clusterModuleSets, clusterArchitectureMaps } + results: SearchResponse, + { + clusters, + clusterHostSets, + clusterInputSets, + clusterModuleSets, + clusterArchitectureMaps, + }: BeatsProcessOptions ) { - const currHits = get(results, 'hits.hits', []); + const currHits = results?.hits?.hits || []; currHits.forEach(hit => { - const clusterUuid = get(hit, '_source.cluster_uuid'); + const clusterUuid = hit._source.cluster_uuid; if (clusters[clusterUuid] === undefined) { clusters[clusterUuid] = getBaseStats(); clusterHostSets[clusterUuid] = new Set(); @@ -57,30 +166,30 @@ export function processResults( const processBeatsStatsResults = () => { const { versions, types, outputs } = clusters[clusterUuid]; - const thisVersion = get(hit, '_source.beats_stats.beat.version'); + const thisVersion = hit._source.beats_stats?.beat?.version; if (thisVersion !== undefined) { const thisVersionAccum = versions[thisVersion] || 0; versions[thisVersion] = thisVersionAccum + 1; } - const thisType = get(hit, '_source.beats_stats.beat.type'); + const thisType = hit._source.beats_stats?.beat?.type; if (thisType !== undefined) { const thisTypeAccum = types[thisType] || 0; types[thisType] = thisTypeAccum + 1; } - const thisOutput = get(hit, '_source.beats_stats.metrics.libbeat.output.type'); + const thisOutput = hit._source.beats_stats?.metrics?.libbeat?.output?.type; if (thisOutput !== undefined) { const thisOutputAccum = outputs[thisOutput] || 0; outputs[thisOutput] = thisOutputAccum + 1; } - const thisEvents = get(hit, '_source.beats_stats.metrics.libbeat.pipeline.events.published'); + const thisEvents = hit._source.beats_stats?.metrics?.libbeat?.pipeline?.events?.published; if (thisEvents !== undefined) { clusters[clusterUuid].eventsPublished += thisEvents; } - const thisHost = get(hit, '_source.beats_stats.beat.host'); + const thisHost = hit._source.beats_stats?.beat?.host; if (thisHost !== undefined) { const hostsMap = clusterHostSets[clusterUuid]; hostsMap.add(thisHost); @@ -89,7 +198,7 @@ export function processResults( }; const processBeatsStateResults = () => { - const stateInput = get(hit, '_source.beats_state.state.input'); + const stateInput = hit._source.beats_state?.state?.input; if (stateInput !== undefined) { const inputSet = clusterInputSets[clusterUuid]; stateInput.names.forEach(name => inputSet.add(name)); @@ -97,8 +206,8 @@ export function processResults( clusters[clusterUuid].input.count += stateInput.count; } - const stateModule = get(hit, '_source.beats_state.state.module'); - const statsType = get(hit, '_source.beats_state.beat.type'); + const stateModule = hit._source.beats_state?.state?.module; + const statsType = hit._source.beats_state?.beat?.type; if (stateModule !== undefined) { const moduleSet = clusterModuleSets[clusterUuid]; stateModule.names.forEach(name => moduleSet.add(statsType + '.' + name)); @@ -106,7 +215,7 @@ export function processResults( clusters[clusterUuid].module.count += stateModule.count; } - const heartbeatState = get(hit, '_source.beats_state.state.heartbeat'); + const heartbeatState = hit._source.beats_state?.state?.heartbeat; if (heartbeatState !== undefined) { if (!clusters[clusterUuid].hasOwnProperty('heartbeat')) { clusters[clusterUuid].heartbeat = { @@ -114,7 +223,7 @@ export function processResults( endpoints: 0, }; } - const clusterHb = clusters[clusterUuid].heartbeat; + const clusterHb = clusters[clusterUuid].heartbeat!; clusterHb.monitors += heartbeatState.monitors; clusterHb.endpoints += heartbeatState.endpoints; @@ -133,12 +242,12 @@ export function processResults( endpoints: 0, }; } - clusterHb[proto].monitors += val.monitors; - clusterHb[proto].endpoints += val.endpoints; + (clusterHb[proto] as HeartbeatBase).monitors += val.monitors; + (clusterHb[proto] as HeartbeatBase).endpoints += val.endpoints; } } - const functionbeatState = get(hit, '_source.beats_state.state.functionbeat'); + const functionbeatState = hit._source.beats_state?.state?.functionbeat; if (functionbeatState !== undefined) { if (!clusters[clusterUuid].hasOwnProperty('functionbeat')) { clusters[clusterUuid].functionbeat = { @@ -148,14 +257,11 @@ export function processResults( }; } - clusters[clusterUuid].functionbeat.functions.count += get( - functionbeatState, - 'functions.count', - 0 - ); + clusters[clusterUuid].functionbeat!.functions.count += + functionbeatState.functions?.count || 0; } - const stateHost = get(hit, '_source.beats_state.state.host'); + const stateHost = hit._source.beats_state?.state?.host; if (stateHost !== undefined) { const hostMap = clusterArchitectureMaps[clusterUuid]; const hostKey = `${stateHost.architecture}/${stateHost.os.platform}`; @@ -198,14 +304,14 @@ export function processResults( * @return {Promise} */ async function fetchBeatsByType( - server, - callCluster, - clusterUuids, - start, - end, - { page = 0, ...options } = {}, - type -) { + server: StatsCollectionConfig['server'], + callCluster: StatsCollectionConfig['callCluster'], + clusterUuids: string[], + start: StatsCollectionConfig['start'], + end: StatsCollectionConfig['end'], + { page = 0, ...options }: { page?: number } & BeatsProcessOptions, + type: string +): Promise { const params = { index: INDEX_PATTERN_BEATS, ignoreUnavailable: true, @@ -232,7 +338,7 @@ async function fetchBeatsByType( { bool: { must_not: { term: { [`${type}.beat.type`]: 'apm-server' } }, - must: { term: { type: type } }, + must: { term: { type } }, }, }, ], @@ -244,8 +350,8 @@ async function fetchBeatsByType( }, }; - const results = await callCluster('search', params); - const hitsLength = get(results, 'hits.hits.length', 0); + const results = await callCluster>('search', params); + const hitsLength = results?.hits?.hits.length || 0; if (hitsLength > 0) { // further augment the clusters object with more stats processResults(results, options); @@ -265,20 +371,40 @@ async function fetchBeatsByType( return Promise.resolve(); } -export async function fetchBeatsStats(...args) { - return fetchBeatsByType(...args, 'beats_stats'); +export async function fetchBeatsStats( + server: StatsCollectionConfig['server'], + callCluster: StatsCollectionConfig['callCluster'], + clusterUuids: string[], + start: StatsCollectionConfig['start'], + end: StatsCollectionConfig['end'], + options: { page?: number } & BeatsProcessOptions +) { + return fetchBeatsByType(server, callCluster, clusterUuids, start, end, options, 'beats_stats'); } -export async function fetchBeatsStates(...args) { - return fetchBeatsByType(...args, 'beats_state'); +export async function fetchBeatsStates( + server: StatsCollectionConfig['server'], + callCluster: StatsCollectionConfig['callCluster'], + clusterUuids: string[], + start: StatsCollectionConfig['start'], + end: StatsCollectionConfig['end'], + options: { page?: number } & BeatsProcessOptions +) { + return fetchBeatsByType(server, callCluster, clusterUuids, start, end, options, 'beats_state'); } /* * Call the function for fetching and summarizing beats stats * @return {Object} - Beats stats in an object keyed by the cluster UUIDs */ -export async function getBeatsStats(server, callCluster, clusterUuids, start, end) { - const options = { +export async function getBeatsStats( + server: StatsCollectionConfig['server'], + callCluster: StatsCollectionConfig['callCluster'], + clusterUuids: string[], + start: StatsCollectionConfig['start'], + end: StatsCollectionConfig['end'] +) { + const options: BeatsProcessOptions = { clusters: {}, // the result object to be built up clusterHostSets: {}, // passed to processResults for tracking state in the results generation clusterInputSets: {}, // passed to processResults for tracking state in the results generation diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_cluster_uuids.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_cluster_uuids.test.ts similarity index 77% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_cluster_uuids.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_cluster_uuids.test.ts index 1f62c677dbb21..4f952b9dec6da 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_cluster_uuids.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_cluster_uuids.test.ts @@ -4,13 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; import sinon from 'sinon'; import { getClusterUuids, fetchClusterUuids, handleClusterUuidsResponse, -} from '../get_cluster_uuids'; +} from './get_cluster_uuids'; describe('get_cluster_uuids', () => { const callCluster = sinon.stub(); @@ -35,20 +34,24 @@ describe('get_cluster_uuids', () => { const expectedUuids = response.aggregations.cluster_uuids.buckets .map(bucket => bucket.key) .map(expectedUuid => ({ clusterUuid: expectedUuid })); - const start = new Date(); - const end = new Date(); + const start = new Date().toISOString(); + const end = new Date().toISOString(); describe('getClusterUuids', () => { it('returns cluster UUIDs', async () => { callCluster.withArgs('search').returns(Promise.resolve(response)); - expect(await getClusterUuids({ server, callCluster, start, end })).to.eql(expectedUuids); + expect( + await getClusterUuids({ server, callCluster, start, end, usageCollection: {} as any }) + ).toStrictEqual(expectedUuids); }); }); describe('fetchClusterUuids', () => { it('searches for clusters', async () => { callCluster.returns(Promise.resolve(response)); - expect(await fetchClusterUuids({ server, callCluster, start, end })).to.be(response); + expect( + await fetchClusterUuids({ server, callCluster, start, end, usageCollection: {} as any }) + ).toStrictEqual(response); }); }); @@ -56,12 +59,12 @@ describe('get_cluster_uuids', () => { // filterPath makes it easy to ignore anything unexpected because it will come back empty it('handles unexpected response', () => { const clusterUuids = handleClusterUuidsResponse({}); - expect(clusterUuids.length).to.be(0); + expect(clusterUuids.length).toStrictEqual(0); }); it('handles valid response', () => { const clusterUuids = handleClusterUuidsResponse(response); - expect(clusterUuids).to.eql(expectedUuids); + expect(clusterUuids).toStrictEqual(expectedUuids); }); it('handles no buckets response', () => { @@ -73,7 +76,7 @@ describe('get_cluster_uuids', () => { }, }); - expect(clusterUuids.length).to.be(0); + expect(clusterUuids.length).toStrictEqual(0); }); }); }); diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_es_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_es_stats.test.ts similarity index 82% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_es_stats.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_es_stats.test.ts index 536e831640fad..70ed2240b47d4 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_es_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_es_stats.test.ts @@ -4,13 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; import sinon from 'sinon'; import { fetchElasticsearchStats, getElasticsearchStats, handleElasticsearchStats, -} from '../get_es_stats'; +} from './get_es_stats'; describe('get_es_stats', () => { const callWith = sinon.stub(); @@ -41,7 +40,9 @@ describe('get_es_stats', () => { it('returns clusters', async () => { callWith.withArgs('search').returns(Promise.resolve(response)); - expect(await getElasticsearchStats(server, callWith, clusterUuids)).to.eql(expectedClusters); + expect(await getElasticsearchStats(server, callWith, clusterUuids)).toStrictEqual( + expectedClusters + ); }); }); @@ -49,28 +50,28 @@ describe('get_es_stats', () => { it('searches for clusters', async () => { callWith.returns(response); - expect(await fetchElasticsearchStats(server, callWith, clusterUuids)).to.be(response); + expect(await fetchElasticsearchStats(server, callWith, clusterUuids)).toStrictEqual(response); }); }); describe('handleElasticsearchStats', () => { // filterPath makes it easy to ignore anything unexpected because it will come back empty it('handles unexpected response', () => { - const clusters = handleElasticsearchStats({}); + const clusters = handleElasticsearchStats({} as any); - expect(clusters.length).to.be(0); + expect(clusters.length).toStrictEqual(0); }); it('handles valid response', () => { - const clusters = handleElasticsearchStats(response); + const clusters = handleElasticsearchStats(response as any); - expect(clusters).to.eql(expectedClusters); + expect(clusters).toStrictEqual(expectedClusters); }); it('handles no hits response', () => { - const clusters = handleElasticsearchStats({ hits: { hits: [] } }); + const clusters = handleElasticsearchStats({ hits: { hits: [] } } as any); - expect(clusters.length).to.be(0); + expect(clusters.length).toStrictEqual(0); }); }); }); diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_es_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_es_stats.ts similarity index 71% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_es_stats.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_es_stats.ts index 52d34258b5fa4..f0ae1163d3f52 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_es_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_es_stats.ts @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { get } from 'lodash'; +import { StatsCollectionConfig } from 'src/legacy/core_plugins/telemetry/server/collection_manager'; +import { SearchResponse } from 'elasticsearch'; import { INDEX_PATTERN_ELASTICSEARCH } from '../../common/constants'; /** @@ -13,10 +14,14 @@ import { INDEX_PATTERN_ELASTICSEARCH } from '../../common/constants'; * @param {Object} server The server instance * @param {function} callCluster The callWithRequest or callWithInternalUser handler * @param {Array} clusterUuids The string Cluster UUIDs to fetch details for - * @return {Promise} Array of the Elasticsearch clusters. */ -export function getElasticsearchStats(server, callCluster, clusterUuids) { - return fetchElasticsearchStats(server, callCluster, clusterUuids).then(handleElasticsearchStats); +export async function getElasticsearchStats( + server: StatsCollectionConfig['server'], + callCluster: StatsCollectionConfig['callCluster'], + clusterUuids: string[] +) { + const response = await fetchElasticsearchStats(server, callCluster, clusterUuids); + return handleElasticsearchStats(response); } /** @@ -25,9 +30,14 @@ export function getElasticsearchStats(server, callCluster, clusterUuids) { * @param {Object} server The server instance * @param {function} callCluster The callWithRequest or callWithInternalUser handler * @param {Array} clusterUuids Cluster UUIDs to limit the request against - * @return {Promise} Response for the aggregations to fetch details for the product. + * + * Returns the response for the aggregations to fetch details for the product. */ -export function fetchElasticsearchStats(server, callCluster, clusterUuids) { +export function fetchElasticsearchStats( + server: StatsCollectionConfig['server'], + callCluster: StatsCollectionConfig['callCluster'], + clusterUuids: string[] +) { const config = server.config(); const params = { index: INDEX_PATTERN_ELASTICSEARCH, @@ -67,13 +77,16 @@ export function fetchElasticsearchStats(server, callCluster, clusterUuids) { return callCluster('search', params); } +export interface ESClusterStats { + cluster_uuid: string; + type: 'cluster_stats'; +} + /** * Extract the cluster stats for each cluster. - * - * @return {Array} The Elasticsearch clusters. */ -export function handleElasticsearchStats(response) { - const clusters = get(response, 'hits.hits', []); +export function handleElasticsearchStats(response: SearchResponse) { + const clusters = response.hits?.hits || []; return clusters.map(cluster => cluster._source); } diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_high_level_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_high_level_stats.test.ts similarity index 91% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_high_level_stats.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_high_level_stats.test.ts index 1c1f8dc888d01..76c80e2eb3d37 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_high_level_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_high_level_stats.test.ts @@ -4,13 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; import sinon from 'sinon'; import { fetchHighLevelStats, getHighLevelStats, handleHighLevelStatsResponse, -} from '../get_high_level_stats'; +} from './get_high_level_stats'; describe('get_high_level_stats', () => { const callWith = sinon.stub(); @@ -244,9 +243,9 @@ describe('get_high_level_stats', () => { it('returns clusters', async () => { callWith.withArgs('search').returns(Promise.resolve(response)); - expect(await getHighLevelStats(server, callWith, clusterUuids, start, end, product)).to.eql( - expectedClusters - ); + expect( + await getHighLevelStats(server, callWith, clusterUuids, start, end, product) + ).toStrictEqual(expectedClusters); }); }); @@ -254,30 +253,30 @@ describe('get_high_level_stats', () => { it('searches for clusters', async () => { callWith.returns(Promise.resolve(response)); - expect(await fetchHighLevelStats(server, callWith, clusterUuids, start, end, product)).to.be( - response - ); + expect( + await fetchHighLevelStats(server, callWith, clusterUuids, start, end, product) + ).toStrictEqual(response); }); }); describe('handleHighLevelStatsResponse', () => { // filterPath makes it easy to ignore anything unexpected because it will come back empty it('handles unexpected response', () => { - const clusters = handleHighLevelStatsResponse({}, product); + const clusters = handleHighLevelStatsResponse({} as any, product); - expect(clusters).to.eql({}); + expect(clusters).toStrictEqual({}); }); it('handles valid response', () => { - const clusters = handleHighLevelStatsResponse(response, product); + const clusters = handleHighLevelStatsResponse(response as any, product); - expect(clusters).to.eql(expectedClusters); + expect(clusters).toStrictEqual(expectedClusters); }); it('handles no hits response', () => { - const clusters = handleHighLevelStatsResponse({ hits: { hits: [] } }, product); + const clusters = handleHighLevelStatsResponse({ hits: { hits: [] } } as any, product); - expect(clusters).to.eql({}); + expect(clusters).toStrictEqual({}); }); }); }); diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_high_level_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_high_level_stats.ts similarity index 66% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_high_level_stats.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_high_level_stats.ts index b87f632308e4d..f67f80940d9f4 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_high_level_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_high_level_stats.ts @@ -5,6 +5,8 @@ */ import { get } from 'lodash'; +import { StatsCollectionConfig } from 'src/legacy/core_plugins/telemetry/server/collection_manager'; +import { SearchResponse } from 'elasticsearch'; import { createQuery } from './create_query'; import { INDEX_PATTERN_KIBANA, @@ -17,13 +19,40 @@ import { TELEMETRY_QUERY_SOURCE, } from '../../common/constants'; +export interface ClusterCloudStats { + name: string; + count: number; + vms: number; + regions: Array<{ region: string; count: number }>; + vm_types: Array<{ vm_type: string; count: number }>; + zones: Array<{ zone: string; count: number }>; +} + +export interface ClusterHighLevelStats { + count: number; + versions: Array<{ version: string; count: number }>; + os: { + platforms: Array<{ platform: string; count: number }>; + platformReleases: Array<{ platformRelease: string; count: number }>; + distros: Array<{ distro: string; count: number }>; + distroReleases: Array<{ distroRelease: string; count: number }>; + }; + cloud: ClusterCloudStats[] | undefined; +} + +export interface ClustersHighLevelStats { + [clusterUuid: string]: ClusterHighLevelStats; +} + +type Counter = Map; + /** * Update a counter associated with the {@code key}. * * @param {Map} map Map to update the counter for the {@code key}. * @param {String} key The key to increment a counter for. */ -function incrementByKey(map, key) { +function incrementByKey(map: Counter, key?: string) { if (!key) { return; } @@ -37,13 +66,29 @@ function incrementByKey(map, key) { map.set(key, count + 1); } +interface InternalCloudMap { + count: number; + unique: Set; + vm_type: Counter; + region: Counter; + zone: Counter; +} + +interface CloudEntry { + id: string; + name: string; + vm_type: string; + region: string; + zone: string; +} + /** * Help to reduce Cloud metrics into unidentifiable metrics (e.g., count IDs so that they can be dropped). * * @param {Map} clouds Existing cloud data by cloud name. * @param {Object} cloud Cloud object loaded from Elasticsearch data. */ -function reduceCloudForCluster(cloudMap, cloud) { +function reduceCloudForCluster(cloudMap: Map, cloud?: CloudEntry) { if (!cloud) { return; } @@ -74,22 +119,48 @@ function reduceCloudForCluster(cloudMap, cloud) { incrementByKey(cloudByName.zone, cloud.zone); } +interface InternalClusterMap { + count: number; + versions: Counter; + cloudMap: Map; + os: { + platforms: Counter; + platformReleases: Counter; + distros: Counter; + distroReleases: Counter; + }; +} + +interface OSData { + platform?: string; + platformRelease?: string; + distro?: string; + distroRelease?: string; +} + /** * Group the instances (hits) by clusters. * * @param {Array} instances Array of hits from the request containing the cluster UUID and version. * @param {String} product The product to limit too ('kibana', 'logstash', 'beats') - * @return {Map} A map of the Cluster UUID to an {@link Object} containing the {@code count} and {@code versions} {@link Map} + * + * Returns a map of the Cluster UUID to an {@link Object} containing the {@code count} and {@code versions} {@link Map} */ -function groupInstancesByCluster(instances, product) { - const clusterMap = new Map(); +function groupInstancesByCluster( + instances: Array<{ _source: T }>, + product: string +) { + const clusterMap = new Map(); // hits are sorted arbitrarily by product UUID instances.map(instance => { - const clusterUuid = get(instance, '_source.cluster_uuid'); - const version = get(instance, `_source.${product}_stats.${product}.version`); - const cloud = get(instance, `_source.${product}_stats.cloud`); - const os = get(instance, `_source.${product}_stats.os`); + const clusterUuid = instance._source.cluster_uuid; + const version: string | undefined = get( + instance, + `_source.${product}_stats.${product}.version` + ); + const cloud: CloudEntry | undefined = get(instance, `_source.${product}_stats.cloud`); + const os: OSData | undefined = get(instance, `_source.${product}_stats.os`); if (clusterUuid) { let cluster = clusterMap.get(clusterUuid); @@ -134,16 +205,12 @@ function groupInstancesByCluster(instances, product) { * { [keyName]: key1, count: value1 }, * { [keyName]: key2, count: value2 } * ] - * - * @param {Map} map [description] - * @param {String} keyName [description] - * @return {Array} [description] */ -function mapToList(map, keyName) { - const list = []; +function mapToList(map: Map, keyName: string): T[] { + const list: T[] = []; for (const [key, count] of map) { - list.push({ [keyName]: key, count }); + list.push(({ [keyName]: key, count } as unknown) as T); } return list; @@ -154,7 +221,7 @@ function mapToList(map, keyName) { * * @param {*} product The product id, which should be in the constants file */ -function getIndexPatternForStackProduct(product) { +function getIndexPatternForStackProduct(product: string) { switch (product) { case KIBANA_SYSTEM_ID: return INDEX_PATTERN_KIBANA; @@ -176,23 +243,41 @@ function getIndexPatternForStackProduct(product) { * @param {Date} start Start time to limit the stats * @param {Date} end End time to limit the stats * @param {String} product The product to limit too ('kibana', 'logstash', 'beats') - * @return {Promise} Object keyed by the cluster UUIDs to make grouping easier. + * + * Returns an object keyed by the cluster UUIDs to make grouping easier. */ -export function getHighLevelStats(server, callCluster, clusterUuids, start, end, product) { - return fetchHighLevelStats( +export async function getHighLevelStats( + server: StatsCollectionConfig['server'], + callCluster: StatsCollectionConfig['callCluster'], + clusterUuids: string[], + start: StatsCollectionConfig['start'], + end: StatsCollectionConfig['end'], + product: string +) { + const response = await fetchHighLevelStats( server, callCluster, clusterUuids, start, end, product - ).then(response => handleHighLevelStatsResponse(response, product)); + ); + return handleHighLevelStatsResponse(response, product); } -export async function fetchHighLevelStats(server, callCluster, clusterUuids, start, end, product) { +export async function fetchHighLevelStats< + T extends { cluster_uuid?: string } = { cluster_uuid?: string } +>( + server: StatsCollectionConfig['server'], + callCluster: StatsCollectionConfig['callCluster'], + clusterUuids: string[], + start: StatsCollectionConfig['start'] | undefined, + end: StatsCollectionConfig['end'] | undefined, + product: string +): Promise> { const config = server.config(); const isKibanaIndex = product === KIBANA_SYSTEM_ID; - const filters = [{ terms: { cluster_uuid: clusterUuids } }]; + const filters: object[] = [{ terms: { cluster_uuid: clusterUuids } }]; // we should supply this from a parameter in the future so that this remains generic if (isKibanaIndex) { @@ -257,13 +342,17 @@ export async function fetchHighLevelStats(server, callCluster, clusterUuids, sta * * @param {Object} response The response from the aggregation * @param {String} product The product to limit too ('kibana', 'logstash', 'beats') - * @return {Object} Object keyed by the cluster UUIDs to make grouping easier. + * + * Returns an object keyed by the cluster UUIDs to make grouping easier. */ -export function handleHighLevelStatsResponse(response, product) { - const instances = get(response, 'hits.hits', []); +export function handleHighLevelStatsResponse( + response: SearchResponse<{ cluster_uuid?: string }>, + product: string +) { + const instances = response.hits?.hits || []; const clusterMap = groupInstancesByCluster(instances, product); - const clusters = {}; + const clusters: ClustersHighLevelStats = {}; for (const [clusterUuid, cluster] of clusterMap) { // it's unlikely this will be an array of more than one, but it is one just incase @@ -271,14 +360,15 @@ export function handleHighLevelStatsResponse(response, product) { // remap the clouds (most likely singular or empty) for (const [name, cloud] of cluster.cloudMap) { - clouds.push({ + const cloudStats: ClusterCloudStats = { name, count: cloud.count, vms: cloud.unique.size, regions: mapToList(cloud.region, 'region'), vm_types: mapToList(cloud.vm_type, 'vm_type'), zones: mapToList(cloud.zone, 'zone'), - }); + }; + clouds.push(cloudStats); } // map stats for product by cluster so that it can be joined with ES cluster stats diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_kibana_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.test.ts similarity index 79% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_kibana_stats.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.test.ts index 98e0afa28fba3..0092e848c827b 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/__tests__/get_kibana_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.test.ts @@ -4,19 +4,25 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getUsageStats, combineStats, rollUpTotals, ensureTimeSpan } from '../get_kibana_stats'; -import expect from '@kbn/expect'; +import { + getUsageStats, + combineStats, + rollUpTotals, + ensureTimeSpan, + KibanaUsageStats, +} from './get_kibana_stats'; +import { SearchResponse } from 'elasticsearch'; describe('Get Kibana Stats', () => { describe('Make a map of usage stats for each cluster', () => { - it('passes through if there are no kibana instances', () => { - const rawStats = {}; - expect(getUsageStats(rawStats)).to.eql({}); + test('passes through if there are no kibana instances', () => { + const rawStats = {} as SearchResponse; + expect(getUsageStats(rawStats)).toStrictEqual({}); }); describe('with single cluster', () => { describe('single index', () => { - it('for a single unused instance', () => { + test('for a single unused instance', () => { const rawStats = { hits: { hits: [ @@ -39,7 +45,7 @@ describe('Get Kibana Stats', () => { }, ], }, - }; + } as any; const expected = { clusterone: { dashboard: { total: 0 }, @@ -53,10 +59,10 @@ describe('Get Kibana Stats', () => { }, }; - expect(getUsageStats(rawStats)).to.eql(expected); + expect(getUsageStats(rawStats)).toStrictEqual(expected); }); - it('for a single instance of active usage', () => { + test('for a single instance of active usage', () => { const rawStats = { hits: { hits: [ @@ -79,7 +85,7 @@ describe('Get Kibana Stats', () => { }, ], }, - }; + } as any; const expected = { clusterone: { dashboard: { total: 1 }, @@ -92,11 +98,49 @@ describe('Get Kibana Stats', () => { plugins: {}, }, }; + expect(getUsageStats(rawStats)).toStrictEqual(expected); + }); - expect(getUsageStats(rawStats)).to.eql(expected); + test('it merges the plugin stats and kibana', () => { + const rawStats = { + hits: { + hits: [ + { + _source: { + cluster_uuid: 'clusterone', + kibana_stats: { + kibana: { version: '7.0.0-alpha1-test02' }, + usage: { + dashboard: { total: 1 }, + visualization: { total: 3 }, + search: { total: 1 }, + index_pattern: { total: 1 }, + graph_workspace: { total: 1 }, + timelion_sheet: { total: 1 }, + index: '.kibana-test-01', + }, + }, + }, + }, + ], + }, + } as any; + const expected = { + clusterone: { + dashboard: { total: 1 }, + visualization: { total: 3 }, + search: { total: 1 }, + index_pattern: { total: 1 }, + graph_workspace: { total: 1 }, + timelion_sheet: { total: 1 }, + indices: 1, + plugins: {}, + }, + }; + expect(getUsageStats(rawStats)).toStrictEqual(expected); }); - it('flattens x-pack stats', () => { + test('flattens x-pack stats', () => { const rawStats = { hits: { hits: [ @@ -126,8 +170,9 @@ describe('Get Kibana Stats', () => { }, ], }, - }; - expect(getUsageStats(rawStats)).to.eql({ + } as any; + + expect(getUsageStats(rawStats)).toStrictEqual({ clusterone: { dashboard: { total: 1 }, visualization: { total: 3 }, @@ -143,7 +188,7 @@ describe('Get Kibana Stats', () => { }); describe('separate indices', () => { - it('with one unused instance', () => { + test('with one unused instance', () => { const rawStats = { hits: { hits: [ @@ -200,7 +245,7 @@ describe('Get Kibana Stats', () => { }, ], }, - }; + } as any; const expected = { clusterone: { dashboard: { total: 1 }, @@ -213,11 +258,10 @@ describe('Get Kibana Stats', () => { plugins: {}, }, }; - - expect(getUsageStats(rawStats)).to.eql(expected); + expect(getUsageStats(rawStats)).toStrictEqual(expected); }); - it('with all actively used instances', () => { + test('with all actively used instances', () => { const rawStats = { hits: { hits: [ @@ -274,7 +318,7 @@ describe('Get Kibana Stats', () => { }, ], }, - }; + } as any; const expected = { clusterone: { dashboard: { total: 4 }, @@ -287,15 +331,14 @@ describe('Get Kibana Stats', () => { plugins: {}, }, }; - - expect(getUsageStats(rawStats)).to.eql(expected); + expect(getUsageStats(rawStats)).toStrictEqual(expected); }); }); }); describe('with multiple clusters', () => { describe('separate indices', () => { - it('with all actively used instances', () => { + test('with all actively used instances', () => { const rawStats = { hits: { hits: [ @@ -369,7 +412,7 @@ describe('Get Kibana Stats', () => { }, ], }, - }; + } as any; const expected = { clusterone: { dashboard: { total: 4 }, @@ -392,29 +435,28 @@ describe('Get Kibana Stats', () => { plugins: {}, }, }; - - expect(getUsageStats(rawStats)).to.eql(expected); + expect(getUsageStats(rawStats)).toStrictEqual(expected); }); }); }); }); describe('Combines usage stats with high-level stats', () => { - it('passes through if there are no kibana instances', () => { + test('passes through if there are no kibana instances', () => { const highLevelStats = {}; const usageStats = {}; - expect(combineStats(highLevelStats, usageStats)).to.eql({}); + expect(combineStats(highLevelStats, usageStats)).toStrictEqual({}); }); describe('adds usage stats to high-level stats', () => { - it('for a single cluster', () => { + test('for a single cluster', () => { const highLevelStats = { clusterone: { count: 2, versions: [{ count: 2, version: '7.0.0-alpha1-test12' }], }, - }; + } as any; const usageStats = { clusterone: { dashboard: { total: 1 }, @@ -428,7 +470,7 @@ describe('Get Kibana Stats', () => { }, }; - expect(combineStats(highLevelStats, usageStats)).to.eql({ + expect(combineStats(highLevelStats, usageStats)).toStrictEqual({ clusterone: { count: 2, dashboard: { total: 1 }, @@ -444,7 +486,7 @@ describe('Get Kibana Stats', () => { }); }); - it('for multiple single clusters', () => { + test('for multiple single clusters', () => { const highLevelStats = { clusterone: { count: 2, @@ -454,7 +496,7 @@ describe('Get Kibana Stats', () => { count: 1, versions: [{ count: 1, version: '7.0.0-alpha1-test14' }], }, - }; + } as any; const usageStats = { clusterone: { dashboard: { total: 1 }, @@ -478,7 +520,7 @@ describe('Get Kibana Stats', () => { }, }; - expect(combineStats(highLevelStats, usageStats)).to.eql({ + expect(combineStats(highLevelStats, usageStats)).toStrictEqual({ clusterone: { count: 2, dashboard: { total: 1 }, @@ -508,16 +550,16 @@ describe('Get Kibana Stats', () => { }); describe('if usage stats are empty', () => { - it('returns just high-level stats', () => { + test('returns just high-level stats', () => { const highLevelStats = { clusterone: { count: 2, versions: [{ count: 2, version: '7.0.0-alpha1-test12' }], }, - }; + } as any; const usageStats = undefined; - expect(combineStats(highLevelStats, usageStats)).to.eql({ + expect(combineStats(highLevelStats, usageStats)).toStrictEqual({ clusterone: { count: 2, versions: [{ count: 2, version: '7.0.0-alpha1-test12' }], @@ -528,64 +570,64 @@ describe('Get Kibana Stats', () => { }); describe('Rolls up stats when there are multiple Kibana indices for a cluster', () => { - it('by combining the `total` fields where previous was 0', () => { - const rollUp = { my_field: { total: 0 } }; + test('by combining the `total` fields where previous was 0', () => { + const rollUp = { my_field: { total: 0 } } as any; const addOn = { my_field: { total: 1 } }; - expect(rollUpTotals(rollUp, addOn, 'my_field')).to.eql({ total: 1 }); + expect(rollUpTotals(rollUp, addOn, 'my_field' as any)).toStrictEqual({ total: 1 }); }); - it('by combining the `total` fields with > 1 for previous and addOn', () => { - const rollUp = { my_field: { total: 1 } }; + test('by combining the `total` fields with > 1 for previous and addOn', () => { + const rollUp = { my_field: { total: 1 } } as any; const addOn = { my_field: { total: 3 } }; - expect(rollUpTotals(rollUp, addOn, 'my_field')).to.eql({ total: 4 }); + expect(rollUpTotals(rollUp, addOn, 'my_field' as any)).toStrictEqual({ total: 4 }); }); }); describe('Ensure minimum time difference', () => { - it('should return start and end as is when none are provided', () => { + test('should return start and end as is when none are provided', () => { const { start, end } = ensureTimeSpan(undefined, undefined); - expect(start).to.be.undefined; - expect(end).to.be.undefined; + expect(start).toBe(undefined); + expect(end).toBe(undefined); }); - it('should return start and end as is when only end is provided', () => { + test('should return start and end as is when only end is provided', () => { const initialEnd = '2020-01-01T00:00:00Z'; const { start, end } = ensureTimeSpan(undefined, initialEnd); - expect(start).to.be.undefined; - expect(end).to.be.equal(initialEnd); + expect(start).toBe(undefined); + expect(end).toEqual(initialEnd); }); - it('should return start and end as is because they are already 24h away', () => { + test('should return start and end as is because they are already 24h away', () => { const initialStart = '2019-12-31T00:00:00Z'; const initialEnd = '2020-01-01T00:00:00Z'; const { start, end } = ensureTimeSpan(initialStart, initialEnd); - expect(start).to.be.equal(initialStart); - expect(end).to.be.equal(initialEnd); + expect(start).toEqual(initialStart); + expect(end).toEqual(initialEnd); }); - it('should return start and end as is because they are already 24h+ away', () => { + test('should return start and end as is because they are already 24h+ away', () => { const initialStart = '2019-12-31T00:00:00Z'; const initialEnd = '2020-01-01T01:00:00Z'; const { start, end } = ensureTimeSpan(initialStart, initialEnd); - expect(start).to.be.equal(initialStart); - expect(end).to.be.equal(initialEnd); + expect(start).toEqual(initialStart); + expect(end).toEqual(initialEnd); }); - it('should modify start to a date 24h before end', () => { + test('should modify start to a date 24h before end', () => { const initialStart = '2020-01-01T00:00:00.000Z'; const initialEnd = '2020-01-01T01:00:00.000Z'; const { start, end } = ensureTimeSpan(initialStart, initialEnd); - expect(start).to.be.equal('2019-12-31T01:00:00.000Z'); - expect(end).to.be.equal(initialEnd); + expect(start).toEqual('2019-12-31T01:00:00.000Z'); + expect(end).toEqual(initialEnd); }); - it('should modify start to a date 24h before now', () => { + test('should modify start to a date 24h before now', () => { const initialStart = new Date().toISOString(); const { start, end } = ensureTimeSpan(initialStart, undefined); - expect(start).to.not.be.equal(initialStart); - expect(end).to.be.undefined; + expect(start).not.toBe(initialStart); + expect(end).toBe(undefined); }); }); }); diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.js b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.ts similarity index 58% rename from x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.js rename to x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.ts index 1e22507c5baf4..e2ad64ce04c6b 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.js +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/get_kibana_stats.ts @@ -5,30 +5,78 @@ */ import moment from 'moment'; -import { get, isEmpty, omit } from 'lodash'; +import { isEmpty } from 'lodash'; +import { StatsCollectionConfig } from 'src/legacy/core_plugins/telemetry/server/collection_manager'; +import { SearchResponse } from 'elasticsearch'; import { KIBANA_SYSTEM_ID, TELEMETRY_COLLECTION_INTERVAL } from '../../common/constants'; -import { fetchHighLevelStats, handleHighLevelStatsResponse } from './get_high_level_stats'; +import { + fetchHighLevelStats, + handleHighLevelStatsResponse, + ClustersHighLevelStats, + ClusterHighLevelStats, +} from './get_high_level_stats'; -export function rollUpTotals(rolledUp, addOn, field) { - const rolledUpTotal = get(rolledUp, [field, 'total'], 0); - const addOnTotal = get(addOn, [field, 'total'], 0); +export function rollUpTotals( + rolledUp: ClusterUsageStats, + addOn: { [key: string]: { total?: number } | undefined }, + field: Exclude +) { + const rolledUpTotal = rolledUp[field]?.total || 0; + const addOnTotal = addOn[field]?.total || 0; return { total: rolledUpTotal + addOnTotal }; } -export function rollUpIndices(rolledUp) { +export function rollUpIndices(rolledUp: ClusterUsageStats) { return rolledUp.indices + 1; } +export interface KibanaUsageStats { + cluster_uuid: string; + kibana_stats?: { + usage?: { + index?: string; + } & { + [plugin: string]: { + total: number; + }; + }; + }; +} + +export interface ClusterUsageStats { + dashboard?: { total: number }; + visualization?: { total: number }; + search?: { total: number }; + index_pattern?: { total: number }; + graph_workspace?: { total: number }; + timelion_sheet?: { total: number }; + indices: number; + plugins?: { + xpack?: unknown; + [plugin: string]: unknown; + }; +} + +export interface ClustersUsageStats { + [clusterUuid: string]: ClusterUsageStats | undefined; +} + +export interface KibanaClusterStat extends Partial, ClusterHighLevelStats {} + +export interface KibanaStats { + [clusterUuid: string]: KibanaClusterStat; +} + /* * @param {Object} rawStats */ -export function getUsageStats(rawStats) { +export function getUsageStats(rawStats: SearchResponse) { const clusterIndexCache = new Set(); - const rawStatsHits = get(rawStats, 'hits.hits', []); + const rawStatsHits = rawStats.hits?.hits || []; // get usage stats per cluster / .kibana index return rawStatsHits.reduce((accum, currInstance) => { - const clusterUuid = get(currInstance, '_source.cluster_uuid'); - const currUsage = get(currInstance, '_source.kibana_stats.usage', {}); + const clusterUuid = currInstance._source.cluster_uuid; + const currUsage = currInstance._source.kibana_stats?.usage || {}; const clusterIndexCombination = clusterUuid + currUsage.index; // return early if usage data is empty or if this cluster/index has already been processed @@ -39,7 +87,7 @@ export function getUsageStats(rawStats) { // Get the stats that were read from any number of different .kibana indices in the cluster, // roll them up into cluster-wide totals - const rolledUpStats = get(accum, clusterUuid, { indices: 0 }); + const rolledUpStats = accum[clusterUuid] || { indices: 0 }; const stats = { dashboard: rollUpTotals(rolledUpStats, currUsage, 'dashboard'), visualization: rollUpTotals(rolledUpStats, currUsage, 'visualization'), @@ -51,21 +99,22 @@ export function getUsageStats(rawStats) { }; // Get the stats provided by telemetry collectors. - const pluginsNested = omit(currUsage, [ - 'index', - 'dashboard', - 'visualization', - 'search', - 'index_pattern', - 'graph_workspace', - 'timelion_sheet', - ]); + const { + index, + dashboard, + visualization, + search, + index_pattern, + graph_workspace, + timelion_sheet, + xpack, + ...pluginsTop + } = currUsage; // Stats filtered by telemetry collectors need to be flattened since they're pulled in a generic way. // A plugin might not provide flat stats if it implements formatForBulkUpload in its collector. // e.g: we want `xpack.reporting` to just be `reporting` - const top = omit(pluginsNested, 'xpack'); - const plugins = { ...top, ...pluginsNested.xpack }; + const plugins = { ...pluginsTop, ...xpack }; return { ...accum, @@ -74,10 +123,13 @@ export function getUsageStats(rawStats) { plugins, }, }; - }, {}); + }, {} as ClustersUsageStats); } -export function combineStats(highLevelStats, usageStats = {}) { +export function combineStats( + highLevelStats: ClustersHighLevelStats, + usageStats: ClustersUsageStats = {} +) { return Object.keys(highLevelStats).reduce((accum, currClusterUuid) => { return { ...accum, @@ -86,7 +138,7 @@ export function combineStats(highLevelStats, usageStats = {}) { ...usageStats[currClusterUuid], }, }; - }, {}); + }, {} as KibanaStats); } /** @@ -96,7 +148,10 @@ export function combineStats(highLevelStats, usageStats = {}) { * @param {date} [start] The start time from which to get the telemetry data * @param {date} [end] The end time from which to get the telemetry data */ -export function ensureTimeSpan(start, end) { +export function ensureTimeSpan( + start?: StatsCollectionConfig['start'], + end?: StatsCollectionConfig['end'] +) { // We only care if we have a start date, because that's the limit that might make us lose the document if (start) { const duration = moment.duration(TELEMETRY_COLLECTION_INTERVAL, 'milliseconds'); @@ -117,9 +172,15 @@ export function ensureTimeSpan(start, end) { * Monkey-patch the modules from get_high_level_stats and add in the * specialized usage data that comes with kibana stats (kibana_stats.usage). */ -export async function getKibanaStats(server, callCluster, clusterUuids, start, end) { +export async function getKibanaStats( + server: StatsCollectionConfig['server'], + callCluster: StatsCollectionConfig['callCluster'], + clusterUuids: string[], + start: StatsCollectionConfig['start'], + end: StatsCollectionConfig['end'] +) { const { start: safeStart, end: safeEnd } = ensureTimeSpan(start, end); - const rawStats = await fetchHighLevelStats( + const rawStats = await fetchHighLevelStats( server, callCluster, clusterUuids, diff --git a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/register_monitoring_collection.ts b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/register_monitoring_collection.ts index 49a925d1dad0b..f0fda5229cb5c 100644 --- a/x-pack/legacy/plugins/monitoring/server/telemetry_collection/register_monitoring_collection.ts +++ b/x-pack/legacy/plugins/monitoring/server/telemetry_collection/register_monitoring_collection.ts @@ -5,7 +5,6 @@ */ import { telemetryCollectionManager } from '../../../../../../src/legacy/core_plugins/telemetry/server'; -// @ts-ignore import { getAllStats } from './get_all_stats'; import { getClusterUuids } from './get_cluster_uuids'; From f49581ce348743731121a6bed0d26fd14ca76580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Mon, 17 Feb 2020 12:05:46 +0000 Subject: [PATCH 11/21] [APM] Divide "Actions menu" into sections to improve readability (#56623) * transaction actions menu * transaction actions menu * fixing pr comments * fixing pr comments * fixing pr comments * fixing pr comments * fixing unit test * fixing unit test * using moment to calculate the timestamp * renaming labels * Changing section subtitle * fixing unit tests * replacing div for react fragment * refactoring * removing marginbottom property * div is needed to remove the margin from the correct element --- .../Links/DiscoverLinks/DiscoverLink.tsx | 29 +- .../components/shared/Links/InfraLink.tsx | 22 +- .../TransactionActionMenu.tsx | 277 ++++------------ .../__test__/TransactionActionMenu.test.tsx | 32 +- .../__test__/sections.test.ts | 204 ++++++++++++ .../shared/TransactionActionMenu/sections.ts | 299 ++++++++++++++++++ .../apm/public/context/ApmPluginContext.tsx | 2 + .../public/components/action_menu.tsx | 8 +- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 10 files changed, 631 insertions(+), 244 deletions(-) create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/__test__/sections.test.ts create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/sections.ts diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/DiscoverLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/DiscoverLink.tsx index 51d8b43dac0ea..b58a450d26644 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/DiscoverLink.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/DiscoverLinks/DiscoverLink.tsx @@ -5,6 +5,7 @@ */ import { EuiLink } from '@elastic/eui'; +import { Location } from 'history'; import React from 'react'; import url from 'url'; import rison, { RisonValue } from 'rison-node'; @@ -12,6 +13,7 @@ import { useLocation } from '../../../../hooks/useLocation'; import { getTimepickerRisonData } from '../rison_helpers'; import { APM_STATIC_INDEX_PATTERN_ID } from '../../../../../common/index_pattern_constants'; import { useApmPluginContext } from '../../../../hooks/useApmPluginContext'; +import { AppMountContextBasePath } from '../../../../context/ApmPluginContext'; interface Props { query: { @@ -30,10 +32,15 @@ interface Props { children: React.ReactNode; } -export function DiscoverLink({ query = {}, ...rest }: Props) { - const { core } = useApmPluginContext(); - const location = useLocation(); - +export const getDiscoverHref = ({ + basePath, + location, + query +}: { + basePath: AppMountContextBasePath; + location: Location; + query: Props['query']; +}) => { const risonQuery = { _g: getTimepickerRisonData(location.search), _a: { @@ -43,11 +50,23 @@ export function DiscoverLink({ query = {}, ...rest }: Props) { }; const href = url.format({ - pathname: core.http.basePath.prepend('/app/kibana'), + pathname: basePath.prepend('/app/kibana'), hash: `/discover?_g=${rison.encode(risonQuery._g)}&_a=${rison.encode( risonQuery._a as RisonValue )}` }); + return href; +}; + +export function DiscoverLink({ query = {}, ...rest }: Props) { + const { core } = useApmPluginContext(); + const location = useLocation(); + + const href = getDiscoverHref({ + basePath: core.http.basePath, + query, + location + }); return ; } diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/InfraLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/InfraLink.tsx index 8ff5e3010d6cc..e4f3557a2ce51 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/Links/InfraLink.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/InfraLink.tsx @@ -10,11 +10,13 @@ import React from 'react'; import url from 'url'; import { fromQuery } from './url_helpers'; import { useApmPluginContext } from '../../../hooks/useApmPluginContext'; +import { AppMountContextBasePath } from '../../../context/ApmPluginContext'; interface InfraQueryParams { time?: number; from?: number; to?: number; + filter?: string; } interface Props extends EuiLinkAnchorProps { @@ -23,12 +25,24 @@ interface Props extends EuiLinkAnchorProps { children?: React.ReactNode; } -export function InfraLink({ path, query = {}, ...rest }: Props) { - const { core } = useApmPluginContext(); +export const getInfraHref = ({ + basePath, + query, + path +}: { + basePath: AppMountContextBasePath; + query: InfraQueryParams; + path?: string; +}) => { const nextSearch = fromQuery(query); - const href = url.format({ - pathname: core.http.basePath.prepend('/app/infra'), + return url.format({ + pathname: basePath.prepend('/app/infra'), hash: compact([path, nextSearch]).join('?') }); +}; + +export function InfraLink({ path, query = {}, ...rest }: Props) { + const { core } = useApmPluginContext(); + const href = getInfraHref({ basePath: core.http.basePath, query, path }); return ; } diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx index 040d29aaa56dd..99f0b0d4fc223 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/TransactionActionMenu.tsx @@ -4,240 +4,85 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiButtonEmpty, - EuiContextMenuItem, - EuiContextMenuPanel, - EuiFlexGroup, - EuiFlexItem, - EuiIcon, - EuiPopover, - EuiLink -} from '@elastic/eui'; -import url from 'url'; +import { EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import React, { useState, FunctionComponent } from 'react'; -import { pick } from 'lodash'; +import React, { FunctionComponent, useState } from 'react'; +import { + ActionMenu, + ActionMenuDivider, + Section, + SectionLink, + SectionLinks, + SectionSubtitle, + SectionTitle +} from '../../../../../../../plugins/observability/public'; import { Transaction } from '../../../../typings/es_schemas/ui/Transaction'; -import { DiscoverTransactionLink } from '../Links/DiscoverLinks/DiscoverTransactionLink'; -import { InfraLink } from '../Links/InfraLink'; -import { useUrlParams } from '../../../hooks/useUrlParams'; -import { fromQuery } from '../Links/url_helpers'; import { useApmPluginContext } from '../../../hooks/useApmPluginContext'; - -function getInfraMetricsQuery(transaction: Transaction) { - const plus5 = new Date(transaction['@timestamp']); - const minus5 = new Date(plus5.getTime()); - - plus5.setMinutes(plus5.getMinutes() + 5); - minus5.setMinutes(minus5.getMinutes() - 5); - - return { - from: minus5.getTime(), - to: plus5.getTime() - }; -} - -function ActionMenuButton({ onClick }: { onClick: () => void }) { - return ( - - {i18n.translate('xpack.apm.transactionActionMenu.actionsButtonLabel', { - defaultMessage: 'Actions' - })} - - ); -} +import { useLocation } from '../../../hooks/useLocation'; +import { useUrlParams } from '../../../hooks/useUrlParams'; +import { getSections } from './sections'; interface Props { readonly transaction: Transaction; } -interface InfraConfigItem { - icon: string; - label: string; - condition?: boolean; - path: string; - query: Record; -} - -export const TransactionActionMenu: FunctionComponent = ( - props: Props -) => { - const { transaction } = props; - +const ActionMenuButton = ({ onClick }: { onClick: () => void }) => ( + + {i18n.translate('xpack.apm.transactionActionMenu.actionsButtonLabel', { + defaultMessage: 'Actions' + })} + +); + +export const TransactionActionMenu: FunctionComponent = ({ + transaction +}: Props) => { const { core } = useApmPluginContext(); - - const [isOpen, setIsOpen] = useState(false); - + const location = useLocation(); const { urlParams } = useUrlParams(); - const hostName = transaction.host?.hostname; - const podId = transaction.kubernetes?.pod.uid; - const containerId = transaction.container?.id; - - const time = Math.round(transaction.timestamp.us / 1000); - const infraMetricsQuery = getInfraMetricsQuery(transaction); - - const infraConfigItems: InfraConfigItem[] = [ - { - icon: 'logsApp', - label: i18n.translate( - 'xpack.apm.transactionActionMenu.showPodLogsLinkLabel', - { defaultMessage: 'Show pod logs' } - ), - condition: !!podId, - path: `/link-to/pod-logs/${podId}`, - query: { time } - }, - { - icon: 'logsApp', - label: i18n.translate( - 'xpack.apm.transactionActionMenu.showContainerLogsLinkLabel', - { defaultMessage: 'Show container logs' } - ), - condition: !!containerId, - path: `/link-to/container-logs/${containerId}`, - query: { time } - }, - { - icon: 'logsApp', - label: i18n.translate( - 'xpack.apm.transactionActionMenu.showHostLogsLinkLabel', - { defaultMessage: 'Show host logs' } - ), - condition: !!hostName, - path: `/link-to/host-logs/${hostName}`, - query: { time } - }, - { - icon: 'logsApp', - label: i18n.translate( - 'xpack.apm.transactionActionMenu.showTraceLogsLinkLabel', - { defaultMessage: 'Show trace logs' } - ), - condition: true, - path: `/link-to/logs`, - query: { - time, - filter: `trace.id:"${transaction.trace.id}" OR ${transaction.trace.id}` - } - }, - { - icon: 'metricsApp', - label: i18n.translate( - 'xpack.apm.transactionActionMenu.showPodMetricsLinkLabel', - { defaultMessage: 'Show pod metrics' } - ), - condition: !!podId, - path: `/link-to/pod-detail/${podId}`, - query: infraMetricsQuery - }, - { - icon: 'metricsApp', - label: i18n.translate( - 'xpack.apm.transactionActionMenu.showContainerMetricsLinkLabel', - { defaultMessage: 'Show container metrics' } - ), - condition: !!containerId, - path: `/link-to/container-detail/${containerId}`, - query: infraMetricsQuery - }, - { - icon: 'metricsApp', - label: i18n.translate( - 'xpack.apm.transactionActionMenu.showHostMetricsLinkLabel', - { defaultMessage: 'Show host metrics' } - ), - condition: !!hostName, - path: `/link-to/host-detail/${hostName}`, - query: infraMetricsQuery - } - ]; - - const infraItems = infraConfigItems.map( - ({ icon, label, condition, path, query }, index) => ({ - icon, - key: `infra-link-${index}`, - child: ( - - {label} - - ), - condition - }) - ); + const [isOpen, setIsOpen] = useState(false); - const uptimeLink = url.format({ - pathname: core.http.basePath.prepend('/app/uptime'), - hash: `/?${fromQuery( - pick( - { - dateRangeStart: urlParams.rangeFrom, - dateRangeEnd: urlParams.rangeTo, - search: `url.domain:"${transaction.url?.domain}"` - }, - (val: string) => !!val - ) - )}` + const sections = getSections({ + transaction, + basePath: core.http.basePath, + location, + urlParams }); - const menuItems = [ - ...infraItems, - { - icon: 'discoverApp', - key: 'discover-transaction', - condition: true, - child: ( - - {i18n.translate( - 'xpack.apm.transactionActionMenu.viewSampleDocumentLinkLabel', - { - defaultMessage: 'View sample document' - } - )} - - ) - }, - { - icon: 'uptimeApp', - key: 'uptime', - child: ( - - {i18n.translate('xpack.apm.transactionActionMenu.viewInUptime', { - defaultMessage: 'View monitor status' - })} - - ), - condition: transaction.url?.domain - } - ] - .filter(({ condition }) => condition) - .map(({ icon, key, child }) => ( - - - {child} - - - - - - )); - return ( - setIsOpen(!isOpen)} />} - isOpen={isOpen} closePopover={() => setIsOpen(false)} + isOpen={isOpen} anchorPosition="downRight" - panelPaddingSize="none" + button={ setIsOpen(!isOpen)} />} > - - + {sections.map((section, idx) => { + const isLastSection = idx !== sections.length - 1; + return ( +

+ {section.map(item => ( +
+ {item.title && {item.title}} + {item.subtitle && ( + {item.subtitle} + )} + + {item.actions.map(action => ( + + ))} + +
+ ))} + {isLastSection && } +
+ ); + })} + ); }; diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/__test__/TransactionActionMenu.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/__test__/TransactionActionMenu.test.tsx index 2bfa5cf1274fa..e9f89034f58ee 100644 --- a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/__test__/TransactionActionMenu.test.tsx +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/__test__/TransactionActionMenu.test.tsx @@ -36,7 +36,7 @@ describe('TransactionActionMenu component', () => { Transactions.transactionWithMinimalData ); - expect(queryByText('Show trace logs')).not.toBeNull(); + expect(queryByText('Trace logs')).not.toBeNull(); }); it('should not render the pod links when there is no pod id', async () => { @@ -44,8 +44,8 @@ describe('TransactionActionMenu component', () => { Transactions.transactionWithMinimalData ); - expect(queryByText('Show pod logs')).toBeNull(); - expect(queryByText('Show pod metrics')).toBeNull(); + expect(queryByText('Pod logs')).toBeNull(); + expect(queryByText('Pod metrics')).toBeNull(); }); it('should render the pod links when there is a pod id', async () => { @@ -53,8 +53,8 @@ describe('TransactionActionMenu component', () => { Transactions.transactionWithKubernetesData ); - expect(queryByText('Show pod logs')).not.toBeNull(); - expect(queryByText('Show pod metrics')).not.toBeNull(); + expect(queryByText('Pod logs')).not.toBeNull(); + expect(queryByText('Pod metrics')).not.toBeNull(); }); it('should not render the container links when there is no container id', async () => { @@ -62,8 +62,8 @@ describe('TransactionActionMenu component', () => { Transactions.transactionWithMinimalData ); - expect(queryByText('Show container logs')).toBeNull(); - expect(queryByText('Show container metrics')).toBeNull(); + expect(queryByText('Container logs')).toBeNull(); + expect(queryByText('Container metrics')).toBeNull(); }); it('should render the container links when there is a container id', async () => { @@ -71,8 +71,8 @@ describe('TransactionActionMenu component', () => { Transactions.transactionWithContainerData ); - expect(queryByText('Show container logs')).not.toBeNull(); - expect(queryByText('Show container metrics')).not.toBeNull(); + expect(queryByText('Container logs')).not.toBeNull(); + expect(queryByText('Container metrics')).not.toBeNull(); }); it('should not render the host links when there is no hostname', async () => { @@ -80,8 +80,8 @@ describe('TransactionActionMenu component', () => { Transactions.transactionWithMinimalData ); - expect(queryByText('Show host logs')).toBeNull(); - expect(queryByText('Show host metrics')).toBeNull(); + expect(queryByText('Host logs')).toBeNull(); + expect(queryByText('Host metrics')).toBeNull(); }); it('should render the host links when there is a hostname', async () => { @@ -89,8 +89,8 @@ describe('TransactionActionMenu component', () => { Transactions.transactionWithHostData ); - expect(queryByText('Show host logs')).not.toBeNull(); - expect(queryByText('Show host metrics')).not.toBeNull(); + expect(queryByText('Host logs')).not.toBeNull(); + expect(queryByText('Host metrics')).not.toBeNull(); }); it('should not render the uptime link if there is no url available', async () => { @@ -98,7 +98,7 @@ describe('TransactionActionMenu component', () => { Transactions.transactionWithMinimalData ); - expect(queryByText('View monitor status')).toBeNull(); + expect(queryByText('Status')).toBeNull(); }); it('should not render the uptime link if there is no domain available', async () => { @@ -106,7 +106,7 @@ describe('TransactionActionMenu component', () => { Transactions.transactionWithUrlWithoutDomain ); - expect(queryByText('View monitor status')).toBeNull(); + expect(queryByText('Status')).toBeNull(); }); it('should render the uptime link if there is a url with a domain', async () => { @@ -114,7 +114,7 @@ describe('TransactionActionMenu component', () => { Transactions.transactionWithUrlAndDomain ); - expect(queryByText('View monitor status')).not.toBeNull(); + expect(queryByText('Status')).not.toBeNull(); }); it('should match the snapshot', async () => { diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/__test__/sections.test.ts b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/__test__/sections.test.ts new file mode 100644 index 0000000000000..52c2d27eabb82 --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/__test__/sections.test.ts @@ -0,0 +1,204 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { Location } from 'history'; +import { getSections } from '../sections'; +import { Transaction } from '../../../../../typings/es_schemas/ui/Transaction'; +import { AppMountContextBasePath } from '../../../../context/ApmPluginContext'; + +describe('Transaction action menu', () => { + const basePath = ({ + prepend: jest.fn() + } as unknown) as AppMountContextBasePath; + const date = '2020-02-06T11:00:00.000Z'; + const timestamp = { us: new Date(date).getTime() }; + + it('shows required sections only', () => { + const transaction = ({ + timestamp, + trace: { id: '123' }, + transaction: { id: '123' }, + '@timestamp': date + } as unknown) as Transaction; + expect( + getSections({ + transaction, + basePath, + location: ({} as unknown) as Location, + urlParams: {} + }) + ).toEqual([ + [ + { + key: 'traceDetails', + title: 'Trace details', + subtitle: 'View trace logs to get further details.', + actions: [ + { + key: 'traceLogs', + label: 'Trace logs', + href: + '#/link-to/logs?time=1580986800&filter=trace.id:%22123%22%20OR%20123', + condition: true + } + ] + } + ], + [ + { + key: 'kibana', + actions: [ + { + key: 'sampleDocument', + label: 'View sample document', + href: + '#/discover?_g=(refreshInterval:(pause:true,value:\'0\'),time:(from:now-24h,to:now))&_a=(index:apm_static_index_pattern_id,interval:auto,query:(language:kuery,query:\'processor.event:"transaction" AND transaction.id:"123" AND trace.id:"123"\'))', + condition: true + } + ] + } + ] + ]); + }); + + it('shows pod and required sections only', () => { + const transaction = ({ + kubernetes: { pod: { uid: '123' } }, + timestamp, + trace: { id: '123' }, + transaction: { id: '123' }, + '@timestamp': date + } as unknown) as Transaction; + expect( + getSections({ + transaction, + basePath, + location: ({} as unknown) as Location, + urlParams: {} + }) + ).toEqual([ + [ + { + key: 'podDetails', + title: 'Pod details', + subtitle: + 'View logs and metrics for this pod to get further details.', + actions: [ + { + key: 'podLogs', + label: 'Pod logs', + href: '#/link-to/pod-logs/123?time=1580986800', + condition: true + }, + { + key: 'podMetrics', + label: 'Pod metrics', + href: + '#/link-to/pod-detail/123?from=1580986500000&to=1580987100000', + condition: true + } + ] + }, + { + key: 'traceDetails', + title: 'Trace details', + subtitle: 'View trace logs to get further details.', + actions: [ + { + key: 'traceLogs', + label: 'Trace logs', + href: + '#/link-to/logs?time=1580986800&filter=trace.id:%22123%22%20OR%20123', + condition: true + } + ] + } + ], + [ + { + key: 'kibana', + actions: [ + { + key: 'sampleDocument', + label: 'View sample document', + href: + '#/discover?_g=(refreshInterval:(pause:true,value:\'0\'),time:(from:now-24h,to:now))&_a=(index:apm_static_index_pattern_id,interval:auto,query:(language:kuery,query:\'processor.event:"transaction" AND transaction.id:"123" AND trace.id:"123"\'))', + condition: true + } + ] + } + ] + ]); + }); + + it('shows host and required sections only', () => { + const transaction = ({ + host: { hostname: 'foo' }, + timestamp, + trace: { id: '123' }, + transaction: { id: '123' }, + '@timestamp': date + } as unknown) as Transaction; + expect( + getSections({ + transaction, + basePath, + location: ({} as unknown) as Location, + urlParams: {} + }) + ).toEqual([ + [ + { + key: 'hostDetails', + title: 'Host details', + subtitle: 'View host logs and metrics to get further details.', + actions: [ + { + key: 'hostLogs', + label: 'Host logs', + href: '#/link-to/host-logs/foo?time=1580986800', + condition: true + }, + { + key: 'hostMetrics', + label: 'Host metrics', + href: + '#/link-to/host-detail/foo?from=1580986500000&to=1580987100000', + condition: true + } + ] + }, + { + key: 'traceDetails', + title: 'Trace details', + subtitle: 'View trace logs to get further details.', + actions: [ + { + key: 'traceLogs', + label: 'Trace logs', + href: + '#/link-to/logs?time=1580986800&filter=trace.id:%22123%22%20OR%20123', + condition: true + } + ] + } + ], + [ + { + key: 'kibana', + actions: [ + { + key: 'sampleDocument', + label: 'View sample document', + href: + '#/discover?_g=(refreshInterval:(pause:true,value:\'0\'),time:(from:now-24h,to:now))&_a=(index:apm_static_index_pattern_id,interval:auto,query:(language:kuery,query:\'processor.event:"transaction" AND transaction.id:"123" AND trace.id:"123"\'))', + condition: true + } + ] + } + ] + ]); + }); +}); diff --git a/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/sections.ts b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/sections.ts new file mode 100644 index 0000000000000..77445a2600960 --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/shared/TransactionActionMenu/sections.ts @@ -0,0 +1,299 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { i18n } from '@kbn/i18n'; +import { Location } from 'history'; +import { pick, isEmpty } from 'lodash'; +import moment from 'moment'; +import url from 'url'; +import { Transaction } from '../../../../typings/es_schemas/ui/Transaction'; +import { IUrlParams } from '../../../context/UrlParamsContext/types'; +import { getDiscoverHref } from '../Links/DiscoverLinks/DiscoverLink'; +import { getDiscoverQuery } from '../Links/DiscoverLinks/DiscoverTransactionLink'; +import { getInfraHref } from '../Links/InfraLink'; +import { fromQuery } from '../Links/url_helpers'; +import { AppMountContextBasePath } from '../../../context/ApmPluginContext'; + +function getInfraMetricsQuery(transaction: Transaction) { + const timestamp = new Date(transaction['@timestamp']).getTime(); + const fiveMinutes = moment.duration(5, 'minutes').asMilliseconds(); + + return { + from: timestamp - fiveMinutes, + to: timestamp + fiveMinutes + }; +} + +interface Action { + key: string; + label: string; + href: string; + condition: boolean; +} + +interface Section { + key: string; + title?: string; + subtitle?: string; + actions: Action[]; +} + +type SectionRecord = Record; + +export const getSections = ({ + transaction, + basePath, + location, + urlParams +}: { + transaction: Transaction; + basePath: AppMountContextBasePath; + location: Location; + urlParams: IUrlParams; +}) => { + const hostName = transaction.host?.hostname; + const podId = transaction.kubernetes?.pod.uid; + const containerId = transaction.container?.id; + + const time = Math.round(transaction.timestamp.us / 1000); + const infraMetricsQuery = getInfraMetricsQuery(transaction); + + const uptimeLink = url.format({ + pathname: basePath.prepend('/app/uptime'), + hash: `/?${fromQuery( + pick( + { + dateRangeStart: urlParams.rangeFrom, + dateRangeEnd: urlParams.rangeTo, + search: `url.domain:"${transaction.url?.domain}"` + }, + (val: string) => !isEmpty(val) + ) + )}` + }); + + const podActions: Action[] = [ + { + key: 'podLogs', + label: i18n.translate( + 'xpack.apm.transactionActionMenu.showPodLogsLinkLabel', + { defaultMessage: 'Pod logs' } + ), + href: getInfraHref({ + basePath, + path: `/link-to/pod-logs/${podId}`, + query: { time } + }), + condition: !!podId + }, + { + key: 'podMetrics', + label: i18n.translate( + 'xpack.apm.transactionActionMenu.showPodMetricsLinkLabel', + { defaultMessage: 'Pod metrics' } + ), + href: getInfraHref({ + basePath, + path: `/link-to/pod-detail/${podId}`, + query: infraMetricsQuery + }), + condition: !!podId + } + ]; + + const containerActions: Action[] = [ + { + key: 'containerLogs', + label: i18n.translate( + 'xpack.apm.transactionActionMenu.showContainerLogsLinkLabel', + { defaultMessage: 'Container logs' } + ), + href: getInfraHref({ + basePath, + path: `/link-to/container-logs/${containerId}`, + query: { time } + }), + condition: !!containerId + }, + { + key: 'containerMetrics', + label: i18n.translate( + 'xpack.apm.transactionActionMenu.showContainerMetricsLinkLabel', + { defaultMessage: 'Container metrics' } + ), + href: getInfraHref({ + basePath, + path: `/link-to/container-detail/${containerId}`, + query: infraMetricsQuery + }), + condition: !!containerId + } + ]; + + const hostActions: Action[] = [ + { + key: 'hostLogs', + label: i18n.translate( + 'xpack.apm.transactionActionMenu.showHostLogsLinkLabel', + { defaultMessage: 'Host logs' } + ), + href: getInfraHref({ + basePath, + path: `/link-to/host-logs/${hostName}`, + query: { time } + }), + condition: !!hostName + }, + { + key: 'hostMetrics', + label: i18n.translate( + 'xpack.apm.transactionActionMenu.showHostMetricsLinkLabel', + { defaultMessage: 'Host metrics' } + ), + href: getInfraHref({ + basePath, + path: `/link-to/host-detail/${hostName}`, + query: infraMetricsQuery + }), + condition: !!hostName + } + ]; + + const logActions: Action[] = [ + { + key: 'traceLogs', + label: i18n.translate( + 'xpack.apm.transactionActionMenu.showTraceLogsLinkLabel', + { defaultMessage: 'Trace logs' } + ), + href: getInfraHref({ + basePath, + path: `/link-to/logs`, + query: { + time, + filter: `trace.id:"${transaction.trace.id}" OR ${transaction.trace.id}` + } + }), + condition: true + } + ]; + + const uptimeActions: Action[] = [ + { + key: 'monitorStatus', + label: i18n.translate('xpack.apm.transactionActionMenu.viewInUptime', { + defaultMessage: 'Status' + }), + href: uptimeLink, + condition: !!transaction.url?.domain + } + ]; + + const kibanaActions: Action[] = [ + { + key: 'sampleDocument', + label: i18n.translate( + 'xpack.apm.transactionActionMenu.viewSampleDocumentLinkLabel', + { + defaultMessage: 'View sample document' + } + ), + href: getDiscoverHref({ + basePath, + query: getDiscoverQuery(transaction), + location + }), + condition: true + } + ]; + + const sectionRecord: SectionRecord = { + observability: [ + { + key: 'podDetails', + title: i18n.translate('xpack.apm.transactionActionMenu.pod.title', { + defaultMessage: 'Pod details' + }), + subtitle: i18n.translate( + 'xpack.apm.transactionActionMenu.pod.subtitle', + { + defaultMessage: + 'View logs and metrics for this pod to get further details.' + } + ), + actions: podActions + }, + { + key: 'containerDetails', + title: i18n.translate( + 'xpack.apm.transactionActionMenu.container.title', + { + defaultMessage: 'Container details' + } + ), + subtitle: i18n.translate( + 'xpack.apm.transactionActionMenu.container.subtitle', + { + defaultMessage: + 'View logs and metrics for this container to get further details.' + } + ), + actions: containerActions + }, + { + key: 'hostDetails', + title: i18n.translate('xpack.apm.transactionActionMenu.host.title', { + defaultMessage: 'Host details' + }), + subtitle: i18n.translate( + 'xpack.apm.transactionActionMenu.host.subtitle', + { + defaultMessage: 'View host logs and metrics to get further details.' + } + ), + actions: hostActions + }, + { + key: 'traceDetails', + title: i18n.translate('xpack.apm.transactionActionMenu.trace.title', { + defaultMessage: 'Trace details' + }), + subtitle: i18n.translate( + 'xpack.apm.transactionActionMenu.trace.subtitle', + { + defaultMessage: 'View trace logs to get further details.' + } + ), + actions: logActions + }, + { + key: 'statusDetails', + title: i18n.translate('xpack.apm.transactionActionMenu.status.title', { + defaultMessage: 'Status details' + }), + subtitle: i18n.translate( + 'xpack.apm.transactionActionMenu.status.subtitle', + { + defaultMessage: 'View status to get further details.' + } + ), + actions: uptimeActions + } + ], + kibana: [{ key: 'kibana', actions: kibanaActions }] + }; + + // Filter out actions that shouldnt be shown and sections without any actions. + return Object.values(sectionRecord) + .map(sections => + sections + .map(section => ({ + ...section, + actions: section.actions.filter(action => action.condition) + })) + .filter(section => !isEmpty(section.actions)) + ) + .filter(sections => !isEmpty(sections)); +}; diff --git a/x-pack/legacy/plugins/apm/public/context/ApmPluginContext.tsx b/x-pack/legacy/plugins/apm/public/context/ApmPluginContext.tsx index 86efd9b31974e..7a9aaa6dfb920 100644 --- a/x-pack/legacy/plugins/apm/public/context/ApmPluginContext.tsx +++ b/x-pack/legacy/plugins/apm/public/context/ApmPluginContext.tsx @@ -8,6 +8,8 @@ import { createContext } from 'react'; import { AppMountContext, PackageInfo } from 'kibana/public'; import { ApmPluginSetupDeps, ConfigSchema } from '../new-platform/plugin'; +export type AppMountContextBasePath = AppMountContext['core']['http']['basePath']; + export interface ApmPluginContextValue { config: ConfigSchema; core: AppMountContext['core']; diff --git a/x-pack/plugins/observability/public/components/action_menu.tsx b/x-pack/plugins/observability/public/components/action_menu.tsx index 6e964dde3aecf..a5f59ecd5506f 100644 --- a/x-pack/plugins/observability/public/components/action_menu.tsx +++ b/x-pack/plugins/observability/public/components/action_menu.tsx @@ -16,6 +16,7 @@ import { import React, { HTMLAttributes } from 'react'; import { EuiListGroupItemProps } from '@elastic/eui/src/components/list_group/list_group_item'; +import styled from 'styled-components'; type Props = EuiPopoverProps & HTMLAttributes; @@ -45,7 +46,12 @@ export const SectionLinks: React.FC<{}> = props => ( export const SectionSpacer: React.FC<{}> = () => ; -export const Section: React.FC<{}> = props => <>{props.children}; +export const Section = styled.div` + margin-bottom: 24px; + &:last-of-type { + margin-bottom: 0; + } +`; export type SectionLinkProps = EuiListGroupItemProps; export const SectionLink: React.FC = props => ( diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index ee2abeff74496..a59a6dbf12566 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -3945,7 +3945,6 @@ "xpack.apm.tracesTable.tracesPerMinuteColumnLabel": "1 分あたりのトレース", "xpack.apm.tracesTable.tracesPerMinuteUnitLabel": "1分あたりトランザクション数", "xpack.apm.transactionActionMenu.actionsButtonLabel": "アクション", - "xpack.apm.transactionActionMenu.actionsLabel": "アクション", "xpack.apm.transactionActionMenu.showContainerLogsLinkLabel": "コンテナーログを表示", "xpack.apm.transactionActionMenu.showContainerMetricsLinkLabel": "コンテナーメトリックを表示", "xpack.apm.transactionActionMenu.showHostLogsLinkLabel": "ホストログを表示", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 3210c619d3e52..dbc9cab4261d8 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3945,7 +3945,6 @@ "xpack.apm.tracesTable.tracesPerMinuteColumnLabel": "每分钟追溯次数", "xpack.apm.tracesTable.tracesPerMinuteUnitLabel": "tpm", "xpack.apm.transactionActionMenu.actionsButtonLabel": "操作", - "xpack.apm.transactionActionMenu.actionsLabel": "操作", "xpack.apm.transactionActionMenu.showContainerLogsLinkLabel": "显示容器日志", "xpack.apm.transactionActionMenu.showContainerMetricsLinkLabel": "显示容器指标", "xpack.apm.transactionActionMenu.showHostLogsLinkLabel": "显示主机日志", From 9388ff7b43d5743dfc8933690f1c67a7befef69d Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Mon, 17 Feb 2020 13:52:53 +0100 Subject: [PATCH 12/21] Fix auto refresh in visualizations and lens (#57667) --- .../visualize/np_ready/editor/editor.js | 8 ----- .../public/embeddable/visualize_embeddable.ts | 8 +++++ .../visualize_embeddable_factory.tsx | 7 +++- .../public/np_ready/public/mocks.ts | 1 + .../public/np_ready/public/plugin.ts | 13 +++++-- .../timefilter/timefilter_service.mock.ts | 3 +- .../embeddable/embeddable.test.tsx | 35 ++++++++++++++++++- .../embeddable/embeddable.tsx | 15 +++++++- .../embeddable/embeddable_factory.ts | 8 ++++- .../public/editor_frame_service/mocks.tsx | 9 ++--- .../public/editor_frame_service/service.tsx | 1 + 11 files changed, 86 insertions(+), 22 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js index 27fb9b63843c4..657104344662f 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js @@ -441,14 +441,6 @@ function VisualizeAppController( }) ); - subscriptions.add( - subscribeWithScope($scope, timefilter.getAutoRefreshFetch$(), { - next: () => { - $scope.vis.forceReload(); - }, - }) - ); - $scope.$on('$destroy', () => { if ($scope._handler) { $scope._handler.destroy(); diff --git a/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable.ts index 5e593398333c9..fddcf70c30605 100644 --- a/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -34,6 +34,7 @@ import { esFilters, Filter, ISearchSource, + TimefilterContract, } from '../../../../../plugins/data/public'; import { EmbeddableInput, @@ -106,8 +107,10 @@ export class VisualizeEmbeddable extends Embeddable { this.handleChanges(); @@ -345,6 +352,7 @@ export class VisualizeEmbeddable extends Embeddable { diff --git a/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx index 03471174753fa..2f00467a85cda 100644 --- a/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx +++ b/src/legacy/core_plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx @@ -38,6 +38,7 @@ import { VISUALIZE_EMBEDDABLE_TYPE } from './constants'; import { getCapabilities, getHttp, getTypes, getUISettings } from '../np_ready/public/services'; import { showNewVisModal } from '../np_ready/public/wizard'; +import { TimefilterContract } from '../../../../../plugins/data/public'; interface VisualizationAttributes extends SavedObjectAttributes { visState: string; @@ -51,7 +52,10 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory< > { public readonly type = VISUALIZE_EMBEDDABLE_TYPE; - constructor(private getSavedVisualizationsLoader: () => SavedVisualizations) { + constructor( + private timefilter: TimefilterContract, + private getSavedVisualizationsLoader: () => SavedVisualizations + ) { super({ savedObjectMetaData: { name: i18n.translate('visualizations.savedObjectName', { defaultMessage: 'Visualization' }), @@ -114,6 +118,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory< const indexPattern = await getIndexPattern(savedObject); const indexPatterns = indexPattern ? [indexPattern] : []; return new VisualizeEmbeddable( + this.timefilter, { savedVisualization: savedObject, indexPatterns, diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts index a948757d7bd83..9fb87cadb2983 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts @@ -56,6 +56,7 @@ const createInstance = async () => { const plugin = new VisualizationsPlugin({} as PluginInitializerContext); const setup = plugin.setup(coreMock.createSetup(), { + data: dataPluginMock.createSetupContract(), expressions: expressionsPluginMock.createSetupContract(), embeddable: embeddablePluginMock.createStartContract(), usageCollection: usageCollectionPluginMock.createSetupContract(), diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts index 36c04923e3fd0..20bed59faad88 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts @@ -36,7 +36,10 @@ import { ExpressionsSetup } from '../../../../../../plugins/expressions/public'; import { IEmbeddableSetup } from '../../../../../../plugins/embeddable/public'; import { visualization as visualizationFunction } from './expressions/visualization_function'; import { visualization as visualizationRenderer } from './expressions/visualization_renderer'; -import { DataPublicPluginStart } from '../../../../../../plugins/data/public'; +import { + DataPublicPluginSetup, + DataPublicPluginStart, +} from '../../../../../../plugins/data/public'; import { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/public'; import { createSavedVisLoader, @@ -65,6 +68,7 @@ export interface VisualizationsSetupDeps { expressions: ExpressionsSetup; embeddable: IEmbeddableSetup; usageCollection: UsageCollectionSetup; + data: DataPublicPluginSetup; } export interface VisualizationsStartDeps { @@ -95,7 +99,7 @@ export class VisualizationsPlugin public setup( core: CoreSetup, - { expressions, embeddable, usageCollection }: VisualizationsSetupDeps + { expressions, embeddable, usageCollection, data }: VisualizationsSetupDeps ): VisualizationsSetup { setUISettings(core.uiSettings); setUsageCollector(usageCollection); @@ -103,7 +107,10 @@ export class VisualizationsPlugin expressions.registerFunction(visualizationFunction); expressions.registerRenderer(visualizationRenderer); - const embeddableFactory = new VisualizeEmbeddableFactory(this.getSavedVisualizationsLoader); + const embeddableFactory = new VisualizeEmbeddableFactory( + data.query.timefilter.timefilter, + this.getSavedVisualizationsLoader + ); embeddable.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory); return { diff --git a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts index 2923cee60f898..80c13464ad98a 100644 --- a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts +++ b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts @@ -18,6 +18,7 @@ */ import { TimefilterService, TimeHistoryContract, TimefilterContract } from '.'; +import { Observable } from 'rxjs'; export type TimefilterServiceClientContract = PublicMethodsOf; @@ -28,7 +29,7 @@ const createSetupContractMock = () => { getEnabledUpdated$: jest.fn(), getTimeUpdate$: jest.fn(), getRefreshIntervalUpdate$: jest.fn(), - getAutoRefreshFetch$: jest.fn(), + getAutoRefreshFetch$: jest.fn(() => new Observable()), getFetch$: jest.fn(), getTime: jest.fn(), setTime: jest.fn(), diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx index a07bd475cdfcb..55363ebe4d8f3 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx @@ -4,10 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ +import { Subject } from 'rxjs'; import { Embeddable } from './embeddable'; import { ReactExpressionRendererProps } from 'src/plugins/expressions/public'; -import { Query, TimeRange, Filter } from 'src/plugins/data/public'; +import { Query, TimeRange, Filter, TimefilterContract } from 'src/plugins/data/public'; import { Document } from '../../persistence'; +import { dataPluginMock } from '../../../../../../../src/plugins/data/public/mocks'; jest.mock('../../../../../../../src/plugins/inspector/public/', () => ({ isAvailable: false, @@ -44,6 +46,7 @@ describe('embeddable', () => { it('should render expression with expression renderer', () => { const embeddable = new Embeddable( + dataPluginMock.createSetupContract().query.timefilter.timefilter, expressionRenderer, { editUrl: '', @@ -64,6 +67,7 @@ describe('embeddable', () => { const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: false } }]; const embeddable = new Embeddable( + dataPluginMock.createSetupContract().query.timefilter.timefilter, expressionRenderer, { editUrl: '', @@ -89,6 +93,7 @@ describe('embeddable', () => { const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: false } }]; const embeddable = new Embeddable( + dataPluginMock.createSetupContract().query.timefilter.timefilter, expressionRenderer, { editUrl: '', @@ -112,6 +117,7 @@ describe('embeddable', () => { const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: true } }]; const embeddable = new Embeddable( + dataPluginMock.createSetupContract().query.timefilter.timefilter, expressionRenderer, { editUrl: '', @@ -130,4 +136,31 @@ describe('embeddable', () => { expect(expressionRenderer).toHaveBeenCalledTimes(1); }); + + it('should re-render on auto refresh fetch observable', () => { + const timeRange: TimeRange = { from: 'now-15d', to: 'now' }; + const query: Query = { language: 'kquery', query: '' }; + const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: true } }]; + + const autoRefreshFetchSubject = new Subject(); + const timefilter = ({ + getAutoRefreshFetch$: () => autoRefreshFetchSubject.asObservable(), + } as unknown) as TimefilterContract; + + const embeddable = new Embeddable( + timefilter, + expressionRenderer, + { + editUrl: '', + editable: true, + savedVis, + }, + { id: '123', timeRange, query, filters } + ); + embeddable.render(mountpoint); + + autoRefreshFetchSubject.next(); + + expect(expressionRenderer).toHaveBeenCalledTimes(2); + }); }); diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx index a3a55f26ff7c2..252ba5c9bc0bc 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx @@ -7,7 +7,13 @@ import _ from 'lodash'; import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { Query, TimeRange, Filter, IIndexPattern } from 'src/plugins/data/public'; +import { + Query, + TimeRange, + Filter, + IIndexPattern, + TimefilterContract, +} from 'src/plugins/data/public'; import { Subscription } from 'rxjs'; import { ReactExpressionRendererType } from '../../../../../../../src/plugins/expressions/public'; import { @@ -43,6 +49,7 @@ export class Embeddable extends AbstractEmbeddable this.onContainerStateChanged(input)); this.onContainerStateChanged(initialInput); + + this.autoRefreshFetchSubscription = timefilter + .getAutoRefreshFetch$() + .subscribe(this.reload.bind(this)); } onContainerStateChanged(containerState: LensEmbeddableInput) { @@ -125,6 +137,7 @@ export class Embeddable extends AbstractEmbeddable, private savedObjectsClient: SavedObjectsClientContract, @@ -85,6 +90,7 @@ export class EmbeddableFactory extends AbstractEmbeddableFactory { ); return new Embeddable( + this.timefilter, this.expressionRenderer, { savedVis, diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/mocks.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/mocks.tsx index cd121a1f96a2b..e606c69c8c386 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/mocks.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/mocks.tsx @@ -14,6 +14,7 @@ import { embeddablePluginMock } from '../../../../../../src/plugins/embeddable/p import { expressionsPluginMock } from '../../../../../../src/plugins/expressions/public/mocks'; import { DatasourcePublicAPI, FramePublicAPI, Datasource, Visualization } from '../types'; import { EditorFrameSetupPlugins, EditorFrameStartPlugins } from './service'; +import { dataPluginMock } from '../../../../../../src/plugins/data/public/mocks'; export function createMockVisualization(): jest.Mocked { return { @@ -103,7 +104,7 @@ export function createExpressionRendererMock(): jest.Mock< export function createMockSetupDependencies() { return ({ - data: {}, + data: dataPluginMock.createSetupContract(), embeddable: embeddablePluginMock.createSetupContract(), expressions: expressionsPluginMock.createSetupContract(), } as unknown) as MockedSetupDependencies; @@ -111,11 +112,7 @@ export function createMockSetupDependencies() { export function createMockStartDependencies() { return ({ - data: { - indexPatterns: { - indexPatterns: {}, - }, - }, + data: dataPluginMock.createSetupContract(), embeddable: embeddablePluginMock.createStartContract(), expressions: expressionsPluginMock.createStartContract(), } as unknown) as MockedStartDependencies; diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_service/service.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_service/service.tsx index 9a3d724705a1a..7a0bb3a2cc50f 100644 --- a/x-pack/legacy/plugins/lens/public/editor_frame_service/service.tsx +++ b/x-pack/legacy/plugins/lens/public/editor_frame_service/service.tsx @@ -79,6 +79,7 @@ export class EditorFrameService { plugins.embeddable.registerEmbeddableFactory( 'lens', new EmbeddableFactory( + plugins.data.query.timefilter.timefilter, core.http, core.application.capabilities, core.savedObjects.client, From ca5e25c1395397a2599c1aec76f752d4fda8d4e8 Mon Sep 17 00:00:00 2001 From: Vadim Dalecky Date: Mon, 17 Feb 2020 14:59:47 +0100 Subject: [PATCH 13/21] Local actions (#57451) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 create UiActionsService * feat: 🎸 add UiActionsServvice.fork() method * feat: 🎸 instantiate UiActionsService in plugin * feat: 🎸 add UiActionsService.registerTrigger(), remove old * feat: 🎸 move attach/detachAction() methods to UiActionsService * refactor: 💡 move remaining actions API to UiActionsService * chore: 🤖 clean up /trigger folder * test: 💍 move registry tests into UiActiosnService tests * fix: 🐛 fix TypeScript typecheck errors * test: 💍 add .fork() trigger tests * feat: 🎸 remove actionIds from ui_actions Trigger interface * fix: 🐛 remove usage of actionIds * fix: 🐛 attach hello world action to trigger in plugin lifecycle * feat: 🎸 fork also trigger to action attachments * fix: 🐛 clear mapping registry in .clear(), improve type --- .../public/hello_world_trigger.ts | 2 - examples/ui_action_examples/public/plugin.ts | 7 +- .../ui_actions_explorer/public/plugin.tsx | 3 - src/plugins/embeddable/public/bootstrap.ts | 17 +- .../lib/panel/embeddable_panel.test.tsx | 5 +- src/plugins/embeddable/public/lib/types.ts | 1 - .../embeddable/public/tests/test_plugin.ts | 8 +- src/plugins/ui_actions/README.md | 14 +- .../incompatible_action_error.ts | 0 .../ui_actions/public/actions/index.ts | 5 +- .../public/actions/register_action.ts | 28 -- src/plugins/ui_actions/public/api.ts | 55 --- src/plugins/ui_actions/public/index.ts | 29 +- src/plugins/ui_actions/public/mocks.ts | 15 +- src/plugins/ui_actions/public/plugin.ts | 39 +- .../{tests/helpers.ts => service/index.ts} | 10 +- .../public/service/ui_actions_service.test.ts | 465 ++++++++++++++++++ .../public/service/ui_actions_service.ts | 194 ++++++++ src/plugins/ui_actions/public/tests/README.md | 2 + .../execute_trigger_actions.test.ts | 33 +- .../get_trigger_actions.test.ts | 5 +- .../get_trigger_compatible_actions.test.ts | 27 +- src/plugins/ui_actions/public/tests/index.ts | 2 +- .../ui_actions/public/tests/test_plugin.ts | 49 -- .../public/triggers/attach_action.ts | 37 -- .../public/triggers/detach_action.ts | 35 -- .../triggers/execute_trigger_actions.ts | 59 --- .../public/triggers/get_trigger.test.ts | 48 -- .../ui_actions/public/triggers/get_trigger.ts | 30 -- .../public/triggers/get_trigger_actions.ts | 29 -- .../get_trigger_compatible_actions.ts | 32 -- .../ui_actions/public/triggers/index.ts | 2 +- .../public/triggers/register_trigger.ts | 28 -- .../public/triggers/registry.test.ts | 149 ------ .../ui_actions/public/triggers/trigger.ts | 1 - src/plugins/ui_actions/public/types.ts | 35 +- 36 files changed, 765 insertions(+), 735 deletions(-) rename src/plugins/ui_actions/public/{triggers => actions}/incompatible_action_error.ts (100%) delete mode 100644 src/plugins/ui_actions/public/actions/register_action.ts delete mode 100644 src/plugins/ui_actions/public/api.ts rename src/plugins/ui_actions/public/{tests/helpers.ts => service/index.ts} (76%) create mode 100644 src/plugins/ui_actions/public/service/ui_actions_service.test.ts create mode 100644 src/plugins/ui_actions/public/service/ui_actions_service.ts create mode 100644 src/plugins/ui_actions/public/tests/README.md rename src/plugins/ui_actions/public/{triggers => tests}/execute_trigger_actions.test.ts (86%) rename src/plugins/ui_actions/public/{triggers => tests}/get_trigger_actions.test.ts (93%) rename src/plugins/ui_actions/public/{triggers => tests}/get_trigger_compatible_actions.test.ts (82%) delete mode 100644 src/plugins/ui_actions/public/tests/test_plugin.ts delete mode 100644 src/plugins/ui_actions/public/triggers/attach_action.ts delete mode 100644 src/plugins/ui_actions/public/triggers/detach_action.ts delete mode 100644 src/plugins/ui_actions/public/triggers/execute_trigger_actions.ts delete mode 100644 src/plugins/ui_actions/public/triggers/get_trigger.test.ts delete mode 100644 src/plugins/ui_actions/public/triggers/get_trigger.ts delete mode 100644 src/plugins/ui_actions/public/triggers/get_trigger_actions.ts delete mode 100644 src/plugins/ui_actions/public/triggers/get_trigger_compatible_actions.ts delete mode 100644 src/plugins/ui_actions/public/triggers/register_trigger.ts delete mode 100644 src/plugins/ui_actions/public/triggers/registry.test.ts diff --git a/examples/ui_action_examples/public/hello_world_trigger.ts b/examples/ui_action_examples/public/hello_world_trigger.ts index 999a7d9864707..929c9aecab17b 100644 --- a/examples/ui_action_examples/public/hello_world_trigger.ts +++ b/examples/ui_action_examples/public/hello_world_trigger.ts @@ -18,11 +18,9 @@ */ import { Trigger } from '../../../src/plugins/ui_actions/public'; -import { HELLO_WORLD_ACTION_TYPE } from './hello_world_action'; export const HELLO_WORLD_TRIGGER_ID = 'HELLO_WORLD_TRIGGER_ID'; export const helloWorldTrigger: Trigger = { id: HELLO_WORLD_TRIGGER_ID, - actionIds: [HELLO_WORLD_ACTION_TYPE], }; diff --git a/examples/ui_action_examples/public/plugin.ts b/examples/ui_action_examples/public/plugin.ts index ef0689227d6bd..bf62b4d973d4d 100644 --- a/examples/ui_action_examples/public/plugin.ts +++ b/examples/ui_action_examples/public/plugin.ts @@ -19,7 +19,7 @@ import { Plugin, CoreSetup, CoreStart } from '../../../src/core/public'; import { UiActionsSetup, UiActionsStart } from '../../../src/plugins/ui_actions/public'; -import { createHelloWorldAction } from './hello_world_action'; +import { createHelloWorldAction, HELLO_WORLD_ACTION_TYPE } from './hello_world_action'; import { helloWorldTrigger } from './hello_world_trigger'; interface UiActionExamplesSetupDependencies { @@ -33,8 +33,9 @@ interface UiActionExamplesStartDependencies { export class UiActionExamplesPlugin implements Plugin { - public setup(core: CoreSetup, deps: UiActionExamplesSetupDependencies) { - deps.uiActions.registerTrigger(helloWorldTrigger); + public setup(core: CoreSetup, { uiActions }: UiActionExamplesSetupDependencies) { + uiActions.registerTrigger(helloWorldTrigger); + uiActions.attachAction(helloWorldTrigger.id, HELLO_WORLD_ACTION_TYPE); } public start(coreStart: CoreStart, deps: UiActionExamplesStartDependencies) { diff --git a/examples/ui_actions_explorer/public/plugin.tsx b/examples/ui_actions_explorer/public/plugin.tsx index 9c5f967a466bf..981ad97a31b46 100644 --- a/examples/ui_actions_explorer/public/plugin.tsx +++ b/examples/ui_actions_explorer/public/plugin.tsx @@ -56,15 +56,12 @@ export class UiActionsExplorerPlugin implements Plugin, deps: SetupDeps) { deps.uiActions.registerTrigger({ id: COUNTRY_TRIGGER, - actionIds: [], }); deps.uiActions.registerTrigger({ id: PHONE_TRIGGER, - actionIds: [], }); deps.uiActions.registerTrigger({ id: USER_TRIGGER, - actionIds: [], }); deps.uiActions.registerAction(lookUpWeatherAction); deps.uiActions.registerAction(viewInMapsAction); diff --git a/src/plugins/embeddable/public/bootstrap.ts b/src/plugins/embeddable/public/bootstrap.ts index 3ca84549c559d..9a364e84092ca 100644 --- a/src/plugins/embeddable/public/bootstrap.ts +++ b/src/plugins/embeddable/public/bootstrap.ts @@ -17,7 +17,7 @@ * under the License. */ -import { UiActionsSetup } from 'src/plugins/ui_actions/public'; +import { UiActionsSetup, Trigger } from 'src/plugins/ui_actions/public'; import { CONTEXT_MENU_TRIGGER, APPLY_FILTER_TRIGGER, @@ -34,35 +34,30 @@ import { * @param api */ export const bootstrap = (uiActions: UiActionsSetup) => { - const triggerContext = { + const triggerContext: Trigger = { id: CONTEXT_MENU_TRIGGER, title: 'Context menu', description: 'Triggered on top-right corner context-menu select.', - actionIds: [], }; - const triggerFilter = { + const triggerFilter: Trigger = { id: APPLY_FILTER_TRIGGER, title: 'Filter click', description: 'Triggered when user applies filter to an embeddable.', - actionIds: [], }; - const triggerBadge = { + const triggerBadge: Trigger = { id: PANEL_BADGE_TRIGGER, title: 'Panel badges', description: 'Actions appear in title bar when an embeddable loads in a panel', - actionIds: [], }; - const selectRangeTrigger = { + const selectRangeTrigger: Trigger = { id: SELECT_RANGE_TRIGGER, title: 'Select range', description: 'Applies a range filter', - actionIds: [], }; - const valueClickTrigger = { + const valueClickTrigger: Trigger = { id: VALUE_CLICK_TRIGGER, title: 'Value clicked', description: 'Value was clicked', - actionIds: [], }; const actionApplyFilter = createFilterAction(); diff --git a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx index 9982c632f36fb..79d59317767d9 100644 --- a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx +++ b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx @@ -25,7 +25,7 @@ import { nextTick } from 'test_utils/enzyme_helpers'; import { findTestSubject } from '@elastic/eui/lib/test'; import { I18nProvider } from '@kbn/i18n/react'; import { CONTEXT_MENU_TRIGGER } from '../triggers'; -import { Action, UiActionsApi } from 'src/plugins/ui_actions/public'; +import { Action, UiActionsStart } from 'src/plugins/ui_actions/public'; import { Trigger, GetEmbeddableFactory, ViewMode } from '../types'; import { EmbeddableFactory, isErrorEmbeddable } from '../embeddables'; import { EmbeddablePanel } from './embeddable_panel'; @@ -52,7 +52,6 @@ const getEmbeddableFactory: GetEmbeddableFactory = (id: string) => embeddableFac const editModeAction = createEditModeAction(); const trigger: Trigger = { id: CONTEXT_MENU_TRIGGER, - actionIds: [editModeAction.id], }; const embeddableFactory = new ContactCardEmbeddableFactory( {} as any, @@ -177,7 +176,7 @@ test('HelloWorldContainer in view mode hides edit mode actions', async () => { const renderInEditModeAndOpenContextMenu = async ( embeddableInputs: any, - getActions: UiActionsApi['getTriggerCompatibleActions'] = () => Promise.resolve([]) + getActions: UiActionsStart['getTriggerCompatibleActions'] = () => Promise.resolve([]) ) => { const inspector = inspectorPluginMock.createStartContract(); diff --git a/src/plugins/embeddable/public/lib/types.ts b/src/plugins/embeddable/public/lib/types.ts index 1bd71163db44c..68ea5bc17f7c9 100644 --- a/src/plugins/embeddable/public/lib/types.ts +++ b/src/plugins/embeddable/public/lib/types.ts @@ -24,7 +24,6 @@ export interface Trigger { id: string; title?: string; description?: string; - actionIds: string[]; } export interface PropertySpec { diff --git a/src/plugins/embeddable/public/tests/test_plugin.ts b/src/plugins/embeddable/public/tests/test_plugin.ts index d9e1a75d92bf3..1edc332780336 100644 --- a/src/plugins/embeddable/public/tests/test_plugin.ts +++ b/src/plugins/embeddable/public/tests/test_plugin.ts @@ -19,8 +19,8 @@ import { CoreSetup, CoreStart } from 'src/core/public'; // eslint-disable-next-line -import { uiActionsTestPlugin } from 'src/plugins/ui_actions/public/tests'; -import { UiActionsApi } from 'src/plugins/ui_actions/public'; +import { uiActionsPluginMock } from 'src/plugins/ui_actions/public/mocks'; +import { UiActionsStart } from 'src/plugins/ui_actions/public'; import { coreMock } from '../../../../core/public/mocks'; import { EmbeddablePublicPlugin, IEmbeddableSetup, IEmbeddableStart } from '../plugin'; @@ -30,14 +30,14 @@ export interface TestPluginReturn { coreStart: CoreStart; setup: IEmbeddableSetup; doStart: (anotherCoreStart?: CoreStart) => IEmbeddableStart; - uiActions: UiActionsApi; + uiActions: UiActionsStart; } export const testPlugin = ( coreSetup: CoreSetup = coreMock.createSetup(), coreStart: CoreStart = coreMock.createStart() ): TestPluginReturn => { - const uiActions = uiActionsTestPlugin(coreSetup, coreStart); + const uiActions = uiActionsPluginMock.createPlugin(coreSetup, coreStart); const initializerContext = {} as any; const plugin = new EmbeddablePublicPlugin(initializerContext); const setup = plugin.setup(coreSetup, { uiActions: uiActions.setup }); diff --git a/src/plugins/ui_actions/README.md b/src/plugins/ui_actions/README.md index 02942b7d5b406..c4e02b551c884 100644 --- a/src/plugins/ui_actions/README.md +++ b/src/plugins/ui_actions/README.md @@ -1,10 +1,10 @@ # UI Actions -An API for: - - creating custom functionality (`actions`) - - creating custom user interaction events (`triggers`) - - attaching and detaching `actions` to `triggers`. - - emitting `trigger` events - - executing `actions` attached to a given `trigger`. - - exposing a context menu for the user to choose the appropriate action when there are multiple actions attached to a single trigger. +An API for: +- creating custom functionality (`actions`) +- creating custom user interaction events (`triggers`) +- attaching and detaching `actions` to `triggers`. +- emitting `trigger` events +- executing `actions` attached to a given `trigger`. +- exposing a context menu for the user to choose the appropriate action when there are multiple actions attached to a single trigger. diff --git a/src/plugins/ui_actions/public/triggers/incompatible_action_error.ts b/src/plugins/ui_actions/public/actions/incompatible_action_error.ts similarity index 100% rename from src/plugins/ui_actions/public/triggers/incompatible_action_error.ts rename to src/plugins/ui_actions/public/actions/incompatible_action_error.ts diff --git a/src/plugins/ui_actions/public/actions/index.ts b/src/plugins/ui_actions/public/actions/index.ts index feb9a8de62eb3..64bfd368e3dfa 100644 --- a/src/plugins/ui_actions/public/actions/index.ts +++ b/src/plugins/ui_actions/public/actions/index.ts @@ -17,5 +17,6 @@ * under the License. */ -export { Action } from './action'; -export { createAction } from './create_action'; +export * from './action'; +export * from './create_action'; +export * from './incompatible_action_error'; diff --git a/src/plugins/ui_actions/public/actions/register_action.ts b/src/plugins/ui_actions/public/actions/register_action.ts deleted file mode 100644 index 5738be63c9592..0000000000000 --- a/src/plugins/ui_actions/public/actions/register_action.ts +++ /dev/null @@ -1,28 +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 { UiActionsApiPure } from '../types'; - -export const registerAction: UiActionsApiPure['registerAction'] = ({ actions }) => action => { - if (actions.has(action.id)) { - throw new Error(`Action [action.id = ${action.id}] already registered.`); - } - - actions.set(action.id, action); -}; diff --git a/src/plugins/ui_actions/public/api.ts b/src/plugins/ui_actions/public/api.ts deleted file mode 100644 index 9a6fd04b14e10..0000000000000 --- a/src/plugins/ui_actions/public/api.ts +++ /dev/null @@ -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 { - UiActionsApi, - UiActionsDependenciesInternal, - UiActionsDependencies, - UiActionsApiPure, -} from './types'; -import { attachAction } from './triggers/attach_action'; -import { detachAction } from './triggers/detach_action'; -import { executeTriggerActions } from './triggers/execute_trigger_actions'; -import { getTrigger } from './triggers/get_trigger'; -import { getTriggerActions } from './triggers/get_trigger_actions'; -import { getTriggerCompatibleActions } from './triggers/get_trigger_compatible_actions'; -import { registerAction } from './actions/register_action'; -import { registerTrigger } from './triggers/register_trigger'; - -export const pureApi: UiActionsApiPure = { - attachAction, - detachAction, - executeTriggerActions, - getTrigger, - getTriggerActions, - getTriggerCompatibleActions, - registerAction, - registerTrigger, -}; - -export const createApi = (deps: UiActionsDependencies) => { - const partialApi: Partial = {}; - const depsInternal: UiActionsDependenciesInternal = { ...deps, api: partialApi }; - for (const [key, fn] of Object.entries(pureApi)) { - (partialApi as any)[key] = fn(depsInternal); - } - Object.freeze(partialApi); - const api = partialApi as UiActionsApi; - return { api, depsInternal }; -}; diff --git a/src/plugins/ui_actions/public/index.ts b/src/plugins/ui_actions/public/index.ts index 427dbecb7aee4..83a08b11fa4c2 100644 --- a/src/plugins/ui_actions/public/index.ts +++ b/src/plugins/ui_actions/public/index.ts @@ -19,19 +19,30 @@ import { PluginInitializerContext } from '../../../core/public'; import { UiActionsPlugin } from './plugin'; +import { UiActionsService } from './service'; export function plugin(initializerContext: PluginInitializerContext) { return new UiActionsPlugin(initializerContext); } export { UiActionsSetup, UiActionsStart } from './plugin'; -export { - Action, - Trigger, - UiActionsApi, - GetActionsCompatibleWithTrigger, - ExecuteTriggerActions, -} from './types'; -export { createAction } from './actions'; +export { UiActionsServiceParams, UiActionsService } from './service'; +export { Action, createAction, IncompatibleActionError } from './actions'; export { buildContextMenuForActions } from './context_menu'; -export { IncompatibleActionError } from './triggers'; +export { Trigger } from './triggers'; + +/** + * @deprecated + * + * Use `UiActionsStart['getTriggerCompatibleActions']` or + * `UiActionsService['getTriggerCompatibleActions']` instead. + */ +export type GetActionsCompatibleWithTrigger = UiActionsService['getTriggerCompatibleActions']; + +/** + * @deprecated + * + * Use `UiActionsStart['executeTriggerActions']` or + * `UiActionsService['executeTriggerActions']` instead. + */ +export type ExecuteTriggerActions = UiActionsService['executeTriggerActions']; diff --git a/src/plugins/ui_actions/public/mocks.ts b/src/plugins/ui_actions/public/mocks.ts index 273c5dcf83e81..d2ba901f1040d 100644 --- a/src/plugins/ui_actions/public/mocks.ts +++ b/src/plugins/ui_actions/public/mocks.ts @@ -17,9 +17,9 @@ * under the License. */ +import { CoreSetup, CoreStart } from 'src/core/public'; import { UiActionsSetup, UiActionsStart } from '.'; import { plugin as pluginInitializer } from '.'; -// eslint-disable-next-line import { coreMock } from '../../../core/public/mocks'; export type Setup = jest.Mocked; @@ -45,17 +45,20 @@ const createStartContract = (): Start => { getTrigger: jest.fn(), getTriggerActions: jest.fn((id: string) => []), getTriggerCompatibleActions: jest.fn(), + clear: jest.fn(), + fork: jest.fn(), }; return startContract; }; -const createPlugin = async () => { +const createPlugin = ( + coreSetup: CoreSetup = coreMock.createSetup(), + coreStart: CoreStart = coreMock.createStart() +) => { const pluginInitializerContext = coreMock.createPluginInitializerContext(); - const coreSetup = coreMock.createSetup(); - const coreStart = coreMock.createStart(); const plugin = pluginInitializer(pluginInitializerContext); - const setup = await plugin.setup(coreSetup); + const setup = plugin.setup(coreSetup); return { pluginInitializerContext, @@ -63,7 +66,7 @@ const createPlugin = async () => { coreStart, plugin, setup, - doStart: async () => await plugin.start(coreStart), + doStart: (anotherCoreStart: CoreStart = coreStart) => plugin.start(anotherCoreStart), }; }; diff --git a/src/plugins/ui_actions/public/plugin.ts b/src/plugins/ui_actions/public/plugin.ts index 12a9b7cbc6526..0874803db7d37 100644 --- a/src/plugins/ui_actions/public/plugin.ts +++ b/src/plugins/ui_actions/public/plugin.ts @@ -17,43 +17,30 @@ * under the License. */ -import { CoreStart, PluginInitializerContext, CoreSetup, Plugin } from 'src/core/public'; -import { UiActionsApi, ActionRegistry, TriggerRegistry } from './types'; -import { createApi } from './api'; - -export interface UiActionsSetup { - attachAction: UiActionsApi['attachAction']; - detachAction: UiActionsApi['detachAction']; - registerAction: UiActionsApi['registerAction']; - registerTrigger: UiActionsApi['registerTrigger']; -} +import { CoreStart, CoreSetup, Plugin, PluginInitializerContext } from 'src/core/public'; +import { UiActionsService } from './service'; + +export type UiActionsSetup = Pick< + UiActionsService, + 'attachAction' | 'detachAction' | 'registerAction' | 'registerTrigger' +>; -export type UiActionsStart = UiActionsApi; +export type UiActionsStart = PublicMethodsOf; export class UiActionsPlugin implements Plugin { - private readonly triggers: TriggerRegistry = new Map(); - private readonly actions: ActionRegistry = new Map(); - private api!: UiActionsApi; + private readonly service = new UiActionsService(); - constructor(initializerContext: PluginInitializerContext) { - this.api = createApi({ triggers: this.triggers, actions: this.actions }).api; - } + constructor(initializerContext: PluginInitializerContext) {} public setup(core: CoreSetup): UiActionsSetup { - return { - registerTrigger: this.api.registerTrigger, - registerAction: this.api.registerAction, - attachAction: this.api.attachAction, - detachAction: this.api.detachAction, - }; + return this.service; } public start(core: CoreStart): UiActionsStart { - return this.api; + return this.service; } public stop() { - this.actions.clear(); - this.triggers.clear(); + this.service.clear(); } } diff --git a/src/plugins/ui_actions/public/tests/helpers.ts b/src/plugins/ui_actions/public/service/index.ts similarity index 76% rename from src/plugins/ui_actions/public/tests/helpers.ts rename to src/plugins/ui_actions/public/service/index.ts index d1a4a71705a81..3998a2ea255cb 100644 --- a/src/plugins/ui_actions/public/tests/helpers.ts +++ b/src/plugins/ui_actions/public/service/index.ts @@ -17,12 +17,4 @@ * under the License. */ -import { UiActionsDependencies } from '../types'; - -export const createDeps = (): UiActionsDependencies => { - const deps: UiActionsDependencies = { - actions: new Map(), - triggers: new Map(), - }; - return deps; -}; +export * from './ui_actions_service'; diff --git a/src/plugins/ui_actions/public/service/ui_actions_service.test.ts b/src/plugins/ui_actions/public/service/ui_actions_service.test.ts new file mode 100644 index 0000000000000..2bbe106c49a25 --- /dev/null +++ b/src/plugins/ui_actions/public/service/ui_actions_service.test.ts @@ -0,0 +1,465 @@ +/* + * 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 { UiActionsService } from './ui_actions_service'; +import { Action } from '../actions'; +import { createRestrictedAction, createHelloWorldAction } from '../tests/test_samples'; +import { ActionRegistry, TriggerRegistry } from '../types'; +import { Trigger } from '../triggers'; + +const testAction1: Action = { + id: 'action1', + order: 1, + type: 'type1', + execute: async () => {}, + getDisplayName: () => 'test1', + getIconType: () => '', + isCompatible: async () => true, +}; + +const testAction2: Action = { + id: 'action2', + order: 2, + type: 'type2', + execute: async () => {}, + getDisplayName: () => 'test2', + getIconType: () => '', + isCompatible: async () => true, +}; + +describe('UiActionsService', () => { + test('can instantiate', () => { + new UiActionsService(); + }); + + describe('.registerTrigger()', () => { + test('can register a trigger', () => { + const service = new UiActionsService(); + service.registerTrigger({ + id: 'test', + }); + }); + }); + + describe('.getTrigger()', () => { + test('can get Trigger from registry', () => { + const service = new UiActionsService(); + service.registerTrigger({ + description: 'foo', + id: 'bar', + title: 'baz', + }); + + const trigger = service.getTrigger('bar'); + + expect(trigger).toEqual({ + description: 'foo', + id: 'bar', + title: 'baz', + }); + }); + + test('throws if trigger does not exist', () => { + const service = new UiActionsService(); + + expect(() => service.getTrigger('foo')).toThrowError( + 'Trigger [triggerId = foo] does not exist.' + ); + }); + }); + + describe('.registerAction()', () => { + test('can register an action', () => { + const service = new UiActionsService(); + service.registerAction({ + id: 'test', + execute: async () => {}, + getDisplayName: () => 'test', + getIconType: () => '', + isCompatible: async () => true, + type: 'test', + }); + }); + }); + + describe('.getTriggerActions()', () => { + const action1: Action = { + id: 'action1', + order: 1, + type: 'type1', + execute: async () => {}, + getDisplayName: () => 'test', + getIconType: () => '', + isCompatible: async () => true, + }; + const action2: Action = { + id: 'action2', + order: 2, + type: 'type2', + execute: async () => {}, + getDisplayName: () => 'test', + getIconType: () => '', + isCompatible: async () => true, + }; + + test('returns actions set on trigger', () => { + const service = new UiActionsService(); + + service.registerAction(action1); + service.registerAction(action2); + service.registerTrigger({ + description: 'foo', + id: 'trigger', + title: 'baz', + }); + + const list0 = service.getTriggerActions('trigger'); + + expect(list0).toHaveLength(0); + + service.attachAction('trigger', 'action1'); + const list1 = service.getTriggerActions('trigger'); + + expect(list1).toHaveLength(1); + expect(list1).toEqual([action1]); + + service.attachAction('trigger', 'action2'); + const list2 = service.getTriggerActions('trigger'); + + expect(list2).toHaveLength(2); + expect(!!list2.find(({ id }: any) => id === 'action1')).toBe(true); + expect(!!list2.find(({ id }: any) => id === 'action2')).toBe(true); + }); + }); + + describe('.getTriggerCompatibleActions()', () => { + test('can register and get actions', async () => { + const actions: ActionRegistry = new Map(); + const service = new UiActionsService({ actions }); + const helloWorldAction = createHelloWorldAction({} as any); + const length = actions.size; + + service.registerAction(helloWorldAction); + + expect(actions.size - length).toBe(1); + expect(actions.get(helloWorldAction.id)).toBe(helloWorldAction); + }); + + test('getTriggerCompatibleActions returns attached actions', async () => { + const service = new UiActionsService(); + const helloWorldAction = createHelloWorldAction({} as any); + + service.registerAction(helloWorldAction); + + const testTrigger: Trigger = { + id: 'MY-TRIGGER', + title: 'My trigger', + }; + service.registerTrigger(testTrigger); + service.attachAction('MY-TRIGGER', helloWorldAction.id); + + const compatibleActions = await service.getTriggerCompatibleActions('MY-TRIGGER', {}); + + expect(compatibleActions.length).toBe(1); + expect(compatibleActions[0].id).toBe(helloWorldAction.id); + }); + + test('filters out actions not applicable based on the context', async () => { + const service = new UiActionsService(); + const restrictedAction = createRestrictedAction<{ accept: boolean }>(context => { + return context.accept; + }); + + service.registerAction(restrictedAction); + + const testTrigger: Trigger = { + id: 'MY-TRIGGER', + title: 'My trigger', + }; + + service.registerTrigger(testTrigger); + service.attachAction(testTrigger.id, restrictedAction.id); + + const compatibleActions1 = await service.getTriggerCompatibleActions(testTrigger.id, { + accept: true, + }); + + expect(compatibleActions1.length).toBe(1); + + const compatibleActions2 = await service.getTriggerCompatibleActions(testTrigger.id, { + accept: false, + }); + + expect(compatibleActions2.length).toBe(0); + }); + + test(`throws an error with an invalid trigger ID`, async () => { + const service = new UiActionsService(); + + await expect(service.getTriggerCompatibleActions('I do not exist', {})).rejects.toMatchObject( + new Error('Trigger [triggerId = I do not exist] does not exist.') + ); + }); + + test('returns empty list if trigger not attached to any action', async () => { + const service = new UiActionsService(); + const testTrigger: Trigger = { + id: '123', + title: '123', + }; + service.registerTrigger(testTrigger); + + const actions = await service.getTriggerCompatibleActions(testTrigger.id, {}); + + expect(actions).toEqual([]); + }); + }); + + describe('.fork()', () => { + test('returns a new instance of the service', () => { + const service1 = new UiActionsService(); + const service2 = service1.fork(); + + expect(service1).not.toBe(service2); + expect(service2).toBeInstanceOf(UiActionsService); + }); + + test('triggers registered in original service are available in original an forked services', () => { + const service1 = new UiActionsService(); + service1.registerTrigger({ + id: 'foo', + }); + const service2 = service1.fork(); + + const trigger1 = service1.getTrigger('foo'); + const trigger2 = service2.getTrigger('foo'); + + expect(trigger1.id).toBe('foo'); + expect(trigger2.id).toBe('foo'); + }); + + test('triggers registered in forked service are not available in original service', () => { + const service1 = new UiActionsService(); + const service2 = service1.fork(); + + service2.registerTrigger({ + id: 'foo', + }); + + expect(() => service1.getTrigger('foo')).toThrowErrorMatchingInlineSnapshot( + `"Trigger [triggerId = foo] does not exist."` + ); + + const trigger2 = service2.getTrigger('foo'); + expect(trigger2.id).toBe('foo'); + }); + + test('forked service preserves trigger-to-actions mapping', () => { + const service1 = new UiActionsService(); + + service1.registerTrigger({ + id: 'foo', + }); + service1.registerAction(testAction1); + service1.attachAction('foo', testAction1.id); + + const service2 = service1.fork(); + + const actions1 = service1.getTriggerActions('foo'); + const actions2 = service2.getTriggerActions('foo'); + + expect(actions1).toHaveLength(1); + expect(actions2).toHaveLength(1); + expect(actions1[0].id).toBe(testAction1.id); + expect(actions2[0].id).toBe(testAction1.id); + }); + + test('new attachments in fork do not appear in original service', () => { + const service1 = new UiActionsService(); + + service1.registerTrigger({ + id: 'foo', + }); + service1.registerAction(testAction1); + service1.registerAction(testAction2); + service1.attachAction('foo', testAction1.id); + + const service2 = service1.fork(); + + expect(service1.getTriggerActions('foo')).toHaveLength(1); + expect(service2.getTriggerActions('foo')).toHaveLength(1); + + service2.attachAction('foo', testAction2.id); + + expect(service1.getTriggerActions('foo')).toHaveLength(1); + expect(service2.getTriggerActions('foo')).toHaveLength(2); + }); + + test('new attachments in original service do not appear in fork', () => { + const service1 = new UiActionsService(); + + service1.registerTrigger({ + id: 'foo', + }); + service1.registerAction(testAction1); + service1.registerAction(testAction2); + service1.attachAction('foo', testAction1.id); + + const service2 = service1.fork(); + + expect(service1.getTriggerActions('foo')).toHaveLength(1); + expect(service2.getTriggerActions('foo')).toHaveLength(1); + + service1.attachAction('foo', testAction2.id); + + expect(service1.getTriggerActions('foo')).toHaveLength(2); + expect(service2.getTriggerActions('foo')).toHaveLength(1); + }); + }); + + describe('registries', () => { + const HELLO_WORLD_ACTION_ID = 'HELLO_WORLD_ACTION_ID'; + + test('can register trigger', () => { + const triggers: TriggerRegistry = new Map(); + const service = new UiActionsService({ triggers }); + + service.registerTrigger({ + description: 'foo', + id: 'bar', + title: 'baz', + }); + + expect(triggers.get('bar')).toEqual({ + description: 'foo', + id: 'bar', + title: 'baz', + }); + }); + + test('can register action', () => { + const actions: ActionRegistry = new Map(); + const service = new UiActionsService({ actions }); + + service.registerAction({ + id: HELLO_WORLD_ACTION_ID, + order: 13, + } as any); + + expect(actions.get(HELLO_WORLD_ACTION_ID)).toMatchObject({ + id: HELLO_WORLD_ACTION_ID, + order: 13, + }); + }); + + test('can attach an action to a trigger', () => { + const service = new UiActionsService(); + + const trigger: Trigger = { + id: 'MY-TRIGGER', + }; + const action = { + id: HELLO_WORLD_ACTION_ID, + order: 25, + } as any; + + service.registerTrigger(trigger); + service.registerAction(action); + service.attachAction('MY-TRIGGER', HELLO_WORLD_ACTION_ID); + + const actions = service.getTriggerActions(trigger.id); + + expect(actions.length).toBe(1); + expect(actions[0].id).toBe(HELLO_WORLD_ACTION_ID); + }); + + test('can detach an action to a trigger', () => { + const service = new UiActionsService(); + + const trigger: Trigger = { + id: 'MY-TRIGGER', + }; + const action = { + id: HELLO_WORLD_ACTION_ID, + order: 25, + } as any; + + service.registerTrigger(trigger); + service.registerAction(action); + service.attachAction(trigger.id, HELLO_WORLD_ACTION_ID); + service.detachAction(trigger.id, HELLO_WORLD_ACTION_ID); + + const actions2 = service.getTriggerActions(trigger.id); + expect(actions2).toEqual([]); + }); + + test('detaching an invalid action from a trigger throws an error', async () => { + const service = new UiActionsService(); + + const action = { + id: HELLO_WORLD_ACTION_ID, + order: 25, + } as any; + + service.registerAction(action); + expect(() => service.detachAction('i do not exist', HELLO_WORLD_ACTION_ID)).toThrowError( + 'No trigger [triggerId = i do not exist] exists, for detaching action [actionId = HELLO_WORLD_ACTION_ID].' + ); + }); + + test('attaching an invalid action to a trigger throws an error', async () => { + const service = new UiActionsService(); + + const action = { + id: HELLO_WORLD_ACTION_ID, + order: 25, + } as any; + + service.registerAction(action); + expect(() => service.attachAction('i do not exist', HELLO_WORLD_ACTION_ID)).toThrowError( + 'No trigger [triggerId = i do not exist] exists, for attaching action [actionId = HELLO_WORLD_ACTION_ID].' + ); + }); + + test('cannot register another action with the same ID', async () => { + const service = new UiActionsService(); + + const action = { + id: HELLO_WORLD_ACTION_ID, + order: 25, + } as any; + + service.registerAction(action); + expect(() => service.registerAction(action)).toThrowError( + 'Action [action.id = HELLO_WORLD_ACTION_ID] already registered.' + ); + }); + + test('cannot register another trigger with the same ID', async () => { + const service = new UiActionsService(); + + const trigger = { id: 'MY-TRIGGER' } as any; + + service.registerTrigger(trigger); + expect(() => service.registerTrigger(trigger)).toThrowError( + 'Trigger [trigger.id = MY-TRIGGER] already registered.' + ); + }); + }); +}); diff --git a/src/plugins/ui_actions/public/service/ui_actions_service.ts b/src/plugins/ui_actions/public/service/ui_actions_service.ts new file mode 100644 index 0000000000000..a62d2aa356435 --- /dev/null +++ b/src/plugins/ui_actions/public/service/ui_actions_service.ts @@ -0,0 +1,194 @@ +/* + * 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 { TriggerRegistry, ActionRegistry, TriggerToActionsRegistry } from '../types'; +import { Action } from '../actions'; +import { Trigger } from '../triggers/trigger'; +import { buildContextMenuForActions, openContextMenu } from '../context_menu'; + +export interface UiActionsServiceParams { + readonly triggers?: TriggerRegistry; + readonly actions?: ActionRegistry; + + /** + * A 1-to-N mapping from `Trigger` to zero or more `Action`. + */ + readonly triggerToActions?: TriggerToActionsRegistry; +} + +export class UiActionsService { + protected readonly triggers: TriggerRegistry; + protected readonly actions: ActionRegistry; + protected readonly triggerToActions: TriggerToActionsRegistry; + + constructor({ + triggers = new Map(), + actions = new Map(), + triggerToActions = new Map(), + }: UiActionsServiceParams = {}) { + this.triggers = triggers; + this.actions = actions; + this.triggerToActions = triggerToActions; + } + + public readonly registerTrigger = (trigger: Trigger) => { + if (this.triggers.has(trigger.id)) { + throw new Error(`Trigger [trigger.id = ${trigger.id}] already registered.`); + } + + this.triggers.set(trigger.id, trigger); + this.triggerToActions.set(trigger.id, []); + }; + + public readonly getTrigger = (id: string) => { + const trigger = this.triggers.get(id); + + if (!trigger) { + throw new Error(`Trigger [triggerId = ${id}] does not exist.`); + } + + return trigger; + }; + + public readonly registerAction = (action: Action) => { + if (this.actions.has(action.id)) { + throw new Error(`Action [action.id = ${action.id}] already registered.`); + } + + this.actions.set(action.id, action); + }; + + public readonly attachAction = (triggerId: string, actionId: string): void => { + const trigger = this.triggers.get(triggerId); + + if (!trigger) { + throw new Error( + `No trigger [triggerId = ${triggerId}] exists, for attaching action [actionId = ${actionId}].` + ); + } + + const actionIds = this.triggerToActions.get(triggerId); + + if (!actionIds!.find(id => id === actionId)) { + this.triggerToActions.set(triggerId, [...actionIds!, actionId]); + } + }; + + public readonly detachAction = (triggerId: string, actionId: string) => { + const trigger = this.triggers.get(triggerId); + + if (!trigger) { + throw new Error( + `No trigger [triggerId = ${triggerId}] exists, for detaching action [actionId = ${actionId}].` + ); + } + + const actionIds = this.triggerToActions.get(triggerId); + + this.triggerToActions.set( + triggerId, + actionIds!.filter(id => id !== actionId) + ); + }; + + public readonly getTriggerActions = (triggerId: string) => { + // This line checks if trigger exists, otherwise throws. + this.getTrigger!(triggerId); + + const actionIds = this.triggerToActions.get(triggerId); + const actions = actionIds! + .map(actionId => this.actions.get(actionId)) + .filter(Boolean) as Action[]; + + return actions; + }; + + public readonly getTriggerCompatibleActions = async (triggerId: string, context: C) => { + const actions = this.getTriggerActions!(triggerId); + const isCompatibles = await Promise.all(actions.map(action => action.isCompatible(context))); + return actions.reduce( + (acc, action, i) => (isCompatibles[i] ? [...acc, action] : acc), + [] + ); + }; + + private async executeSingleAction(action: Action, actionContext: A) { + const href = action.getHref && action.getHref(actionContext); + + if (href) { + window.location.href = href; + return; + } + + await action.execute(actionContext); + } + + private async executeMultipleActions(actions: Action[], actionContext: C) { + const panel = await buildContextMenuForActions({ + actions, + actionContext, + closeMenu: () => session.close(), + }); + const session = openContextMenu([panel]); + } + + public readonly executeTriggerActions = async (triggerId: string, actionContext: C) => { + const actions = await this.getTriggerCompatibleActions!(triggerId, actionContext); + + if (!actions.length) { + throw new Error( + `No compatible actions found to execute for trigger [triggerId = ${triggerId}].` + ); + } + + if (actions.length === 1) { + await this.executeSingleAction(actions[0], actionContext); + return; + } + + await this.executeMultipleActions(actions, actionContext); + }; + + /** + * Removes all registered triggers and actions. + */ + public readonly clear = () => { + this.actions.clear(); + this.triggers.clear(); + this.triggerToActions.clear(); + }; + + /** + * "Fork" a separate instance of `UiActionsService` that inherits all existing + * triggers and actions, but going forward all new triggers and actions added + * to this instance of `UiActionsService` are only available within this instance. + */ + public readonly fork = (): UiActionsService => { + const triggers: TriggerRegistry = new Map(); + const actions: ActionRegistry = new Map(); + const triggerToActions: TriggerToActionsRegistry = new Map(); + + for (const [key, value] of this.triggers.entries()) triggers.set(key, value); + for (const [key, value] of this.actions.entries()) actions.set(key, value); + for (const [key, value] of this.triggerToActions.entries()) + triggerToActions.set(key, [...value]); + + return new UiActionsService({ triggers, actions, triggerToActions }); + }; +} diff --git a/src/plugins/ui_actions/public/tests/README.md b/src/plugins/ui_actions/public/tests/README.md new file mode 100644 index 0000000000000..8ea3a89e7c120 --- /dev/null +++ b/src/plugins/ui_actions/public/tests/README.md @@ -0,0 +1,2 @@ +This folder contains integration tests for the `ui_actions` plugin and +`test_samples` that other plugins can use in their tests. diff --git a/src/plugins/ui_actions/public/triggers/execute_trigger_actions.test.ts b/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts similarity index 86% rename from src/plugins/ui_actions/public/triggers/execute_trigger_actions.test.ts rename to src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts index 7f2506daee268..f8c196a623499 100644 --- a/src/plugins/ui_actions/public/triggers/execute_trigger_actions.test.ts +++ b/src/plugins/ui_actions/public/tests/execute_trigger_actions.test.ts @@ -19,7 +19,8 @@ import { Action, createAction } from '../actions'; import { openContextMenu } from '../context_menu'; -import { UiActionsTestPluginReturn, uiActionsTestPlugin } from '../tests/test_plugin'; +import { uiActionsPluginMock } from '../mocks'; +import { Trigger } from '../triggers'; jest.mock('../context_menu'); @@ -37,14 +38,14 @@ function createTestAction(id: string, checkCompatibility: (context: A) => boo }); } -let uiActions: UiActionsTestPluginReturn; +let uiActions: ReturnType; const reset = () => { - uiActions = uiActionsTestPlugin(); + uiActions = uiActionsPluginMock.createPlugin(); uiActions.setup.registerTrigger({ id: CONTACT_USER_TRIGGER, - actionIds: ['SEND_MESSAGE_ACTION'], }); + uiActions.setup.attachAction(CONTACT_USER_TRIGGER, 'SEND_MESSAGE_ACTION'); executeFn.mockReset(); openContextMenuSpy.mockReset(); @@ -53,14 +54,15 @@ beforeEach(reset); test('executes a single action mapped to a trigger', async () => { const { setup, doStart } = uiActions; - const trigger = { + const trigger: Trigger = { id: 'MY-TRIGGER', title: 'My trigger', - actionIds: ['test1'], }; const action = createTestAction('test1', () => true); + setup.registerTrigger(trigger); setup.registerAction(action); + setup.attachAction(trigger.id, 'test1'); const context = {}; const start = doStart(); @@ -72,12 +74,13 @@ test('executes a single action mapped to a trigger', async () => { test('throws an error if there are no compatible actions to execute', async () => { const { setup, doStart } = uiActions; - const trigger = { + const trigger: Trigger = { id: 'MY-TRIGGER', title: 'My trigger', - actionIds: ['testaction'], }; + setup.registerTrigger(trigger); + setup.attachAction(trigger.id, 'testaction'); const context = {}; const start = doStart(); @@ -88,14 +91,15 @@ test('throws an error if there are no compatible actions to execute', async () = test('does not execute an incompatible action', async () => { const { setup, doStart } = uiActions; - const trigger = { + const trigger: Trigger = { id: 'MY-TRIGGER', title: 'My trigger', - actionIds: ['test1'], }; const action = createTestAction<{ name: string }>('test1', ({ name }) => name === 'executeme'); + setup.registerTrigger(trigger); setup.registerAction(action); + setup.attachAction(trigger.id, 'test1'); const start = doStart(); const context = { @@ -108,16 +112,18 @@ test('does not execute an incompatible action', async () => { test('shows a context menu when more than one action is mapped to a trigger', async () => { const { setup, doStart } = uiActions; - const trigger = { + const trigger: Trigger = { id: 'MY-TRIGGER', title: 'My trigger', - actionIds: ['test1', 'test2'], }; const action1 = createTestAction('test1', () => true); const action2 = createTestAction('test2', () => true); + setup.registerTrigger(trigger); setup.registerAction(action1); setup.registerAction(action2); + setup.attachAction(trigger.id, 'test1'); + setup.attachAction(trigger.id, 'test2'); expect(openContextMenu).toHaveBeenCalledTimes(0); @@ -134,7 +140,6 @@ test('passes whole action context to isCompatible()', async () => { const trigger = { id: 'MY-TRIGGER', title: 'My trigger', - actionIds: ['test'], }; const action = createTestAction<{ foo: string }>('test', ({ foo }) => { expect(foo).toEqual('bar'); @@ -143,6 +148,8 @@ test('passes whole action context to isCompatible()', async () => { setup.registerTrigger(trigger); setup.registerAction(action); + setup.attachAction(trigger.id, 'test'); + const start = doStart(); const context = { foo: 'bar' }; diff --git a/src/plugins/ui_actions/public/triggers/get_trigger_actions.test.ts b/src/plugins/ui_actions/public/tests/get_trigger_actions.test.ts similarity index 93% rename from src/plugins/ui_actions/public/triggers/get_trigger_actions.test.ts rename to src/plugins/ui_actions/public/tests/get_trigger_actions.test.ts index aef4114ffb4c6..e91acd4c7151b 100644 --- a/src/plugins/ui_actions/public/triggers/get_trigger_actions.test.ts +++ b/src/plugins/ui_actions/public/tests/get_trigger_actions.test.ts @@ -18,7 +18,7 @@ */ import { Action } from '../actions'; -import { uiActionsTestPlugin } from '../tests/test_plugin'; +import { uiActionsPluginMock } from '../mocks'; const action1: Action = { id: 'action1', @@ -32,11 +32,10 @@ const action2: Action = { } as any; test('returns actions set on trigger', () => { - const { setup, doStart } = uiActionsTestPlugin(); + const { setup, doStart } = uiActionsPluginMock.createPlugin(); setup.registerAction(action1); setup.registerAction(action2); setup.registerTrigger({ - actionIds: [], description: 'foo', id: 'trigger', title: 'baz', diff --git a/src/plugins/ui_actions/public/triggers/get_trigger_compatible_actions.test.ts b/src/plugins/ui_actions/public/tests/get_trigger_compatible_actions.test.ts similarity index 82% rename from src/plugins/ui_actions/public/triggers/get_trigger_compatible_actions.test.ts rename to src/plugins/ui_actions/public/tests/get_trigger_compatible_actions.test.ts index f4d2ea48ff6b9..a966003973aba 100644 --- a/src/plugins/ui_actions/public/triggers/get_trigger_compatible_actions.test.ts +++ b/src/plugins/ui_actions/public/tests/get_trigger_compatible_actions.test.ts @@ -18,35 +18,30 @@ */ import { createSayHelloAction } from '../tests/test_samples/say_hello_action'; -import { UiActionsTestPluginReturn, uiActionsTestPlugin } from '../tests/test_plugin'; +import { uiActionsPluginMock } from '../mocks'; import { createRestrictedAction, createHelloWorldAction } from '../tests/test_samples'; import { Action } from '../actions'; +import { Trigger } from '../triggers'; let action: Action<{ name: string }>; -let uiActions: UiActionsTestPluginReturn; +let uiActions: ReturnType; beforeEach(() => { - uiActions = uiActionsTestPlugin(); + uiActions = uiActionsPluginMock.createPlugin(); action = createSayHelloAction({} as any); uiActions.setup.registerAction(action); uiActions.setup.registerTrigger({ id: 'trigger', title: 'trigger', - actionIds: [], }); uiActions.setup.attachAction('trigger', action.id); }); -test('can register and get actions', async () => { - const { setup, plugin } = uiActions; +test('can register action', async () => { + const { setup } = uiActions; const helloWorldAction = createHelloWorldAction({} as any); - const length = (plugin as any).actions.size; setup.registerAction(helloWorldAction); - - expect((plugin as any).actions.size - length).toBe(1); - expect((plugin as any).actions.get(action.id)).toBe(action); - expect((plugin as any).actions.get(helloWorldAction.id)).toBe(helloWorldAction); }); test('getTriggerCompatibleActions returns attached actions', async () => { @@ -55,10 +50,9 @@ test('getTriggerCompatibleActions returns attached actions', async () => { setup.registerAction(helloWorldAction); - const testTrigger = { + const testTrigger: Trigger = { id: 'MY-TRIGGER', title: 'My trigger', - actionIds: [], }; setup.registerTrigger(testTrigger); setup.attachAction('MY-TRIGGER', helloWorldAction.id); @@ -78,13 +72,13 @@ test('filters out actions not applicable based on the context', async () => { setup.registerAction(restrictedAction); - const testTrigger = { + const testTrigger: Trigger = { id: 'MY-TRIGGER', title: 'My trigger', - actionIds: [restrictedAction.id], }; setup.registerTrigger(testTrigger); + setup.attachAction(testTrigger.id, restrictedAction.id); const start = doStart(); let actions = await start.getTriggerCompatibleActions(testTrigger.id, { accept: true }); @@ -107,10 +101,9 @@ test(`throws an error with an invalid trigger ID`, async () => { test(`with a trigger mapping that maps to an non-existing action returns empty list`, async () => { const { setup, doStart } = uiActions; - const testTrigger = { + const testTrigger: Trigger = { id: '123', title: '123', - actionIds: ['I do not exist'], }; setup.registerTrigger(testTrigger); diff --git a/src/plugins/ui_actions/public/tests/index.ts b/src/plugins/ui_actions/public/tests/index.ts index 6f5610a7beb64..dbc34abb8acb4 100644 --- a/src/plugins/ui_actions/public/tests/index.ts +++ b/src/plugins/ui_actions/public/tests/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export { uiActionsTestPlugin } from './test_plugin'; +export * from './test_samples'; diff --git a/src/plugins/ui_actions/public/tests/test_plugin.ts b/src/plugins/ui_actions/public/tests/test_plugin.ts deleted file mode 100644 index dcc42fd9f6fb2..0000000000000 --- a/src/plugins/ui_actions/public/tests/test_plugin.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { CoreSetup, CoreStart } from 'src/core/public'; -import { UiActionsPlugin, UiActionsSetup, UiActionsStart } from '../plugin'; - -export interface UiActionsTestPluginReturn { - plugin: UiActionsPlugin; - coreSetup: CoreSetup; - coreStart: CoreStart; - setup: UiActionsSetup; - doStart: (anotherCoreStart?: CoreStart) => UiActionsStart; -} - -export const uiActionsTestPlugin = ( - coreSetup: CoreSetup = {} as CoreSetup, - coreStart: CoreStart = {} as CoreStart -): UiActionsTestPluginReturn => { - const initializerContext = {} as any; - const plugin = new UiActionsPlugin(initializerContext); - const setup = plugin.setup(coreSetup); - - return { - plugin, - coreSetup, - coreStart, - setup, - doStart: (anotherCoreStart: CoreStart = coreStart) => { - const start = plugin.start(anotherCoreStart); - return start; - }, - }; -}; diff --git a/src/plugins/ui_actions/public/triggers/attach_action.ts b/src/plugins/ui_actions/public/triggers/attach_action.ts deleted file mode 100644 index 6c0beeae2bcd7..0000000000000 --- a/src/plugins/ui_actions/public/triggers/attach_action.ts +++ /dev/null @@ -1,37 +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 { UiActionsApiPure } from '../types'; - -export const attachAction: UiActionsApiPure['attachAction'] = ({ triggers }) => ( - triggerId, - actionId -) => { - const trigger = triggers.get(triggerId); - - if (!trigger) { - throw new Error( - `No trigger [triggerId = ${triggerId}] exists, for attaching action [actionId = ${actionId}].` - ); - } - - if (!trigger.actionIds.find(id => id === actionId)) { - trigger.actionIds.push(actionId); - } -}; diff --git a/src/plugins/ui_actions/public/triggers/detach_action.ts b/src/plugins/ui_actions/public/triggers/detach_action.ts deleted file mode 100644 index 710dcf9f5621b..0000000000000 --- a/src/plugins/ui_actions/public/triggers/detach_action.ts +++ /dev/null @@ -1,35 +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 { UiActionsApiPure } from '../types'; - -export const detachAction: UiActionsApiPure['detachAction'] = ({ triggers }) => ( - triggerId, - actionId -) => { - const trigger = triggers.get(triggerId); - - if (!trigger) { - throw new Error( - `No trigger [triggerId = ${triggerId}] exists, for detaching action [actionId = ${actionId}].` - ); - } - - trigger.actionIds = trigger.actionIds.filter(id => id !== actionId); -}; diff --git a/src/plugins/ui_actions/public/triggers/execute_trigger_actions.ts b/src/plugins/ui_actions/public/triggers/execute_trigger_actions.ts deleted file mode 100644 index 71f69eb3bdc29..0000000000000 --- a/src/plugins/ui_actions/public/triggers/execute_trigger_actions.ts +++ /dev/null @@ -1,59 +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 { UiActionsApiPure } from '../types'; -import { buildContextMenuForActions, openContextMenu } from '../context_menu'; -import { Action } from '../actions'; - -const executeSingleAction = async (action: Action, actionContext: A) => { - const href = action.getHref && action.getHref(actionContext); - - // TODO: Do we need a `getHref()` special case? - if (href) { - window.location.href = href; - return; - } - - await action.execute(actionContext); -}; - -export const executeTriggerActions: UiActionsApiPure['executeTriggerActions'] = ({ api }) => async ( - triggerId, - actionContext -) => { - const actions = await api.getTriggerCompatibleActions!(triggerId, actionContext); - - if (!actions.length) { - throw new Error( - `No compatible actions found to execute for trigger [triggerId = ${triggerId}].` - ); - } - - if (actions.length === 1) { - await executeSingleAction(actions[0], actionContext); - return; - } - - const panel = await buildContextMenuForActions({ - actions, - actionContext, - closeMenu: () => session.close(), - }); - const session = openContextMenu([panel]); -}; diff --git a/src/plugins/ui_actions/public/triggers/get_trigger.test.ts b/src/plugins/ui_actions/public/triggers/get_trigger.test.ts deleted file mode 100644 index 88dd5a8990c9d..0000000000000 --- a/src/plugins/ui_actions/public/triggers/get_trigger.test.ts +++ /dev/null @@ -1,48 +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 '../api'; -import { createDeps } from '../tests/helpers'; - -test('can get Trigger from registry', () => { - const deps = createDeps(); - const { api } = createApi(deps); - api.registerTrigger({ - actionIds: [], - description: 'foo', - id: 'bar', - title: 'baz', - }); - - const trigger = api.getTrigger('bar'); - - expect(trigger).toEqual({ - actionIds: [], - description: 'foo', - id: 'bar', - title: 'baz', - }); -}); - -test('throws if trigger does not exist', () => { - const deps = createDeps(); - const { api } = createApi(deps); - - expect(() => api.getTrigger('foo')).toThrowError('Trigger [triggerId = foo] does not exist.'); -}); diff --git a/src/plugins/ui_actions/public/triggers/get_trigger.ts b/src/plugins/ui_actions/public/triggers/get_trigger.ts deleted file mode 100644 index 5c96200261a90..0000000000000 --- a/src/plugins/ui_actions/public/triggers/get_trigger.ts +++ /dev/null @@ -1,30 +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 { UiActionsApiPure } from '../types'; - -export const getTrigger: UiActionsApiPure['getTrigger'] = ({ triggers }) => id => { - const trigger = triggers.get(id); - - if (!trigger) { - throw new Error(`Trigger [triggerId = ${id}] does not exist.`); - } - - return trigger; -}; diff --git a/src/plugins/ui_actions/public/triggers/get_trigger_actions.ts b/src/plugins/ui_actions/public/triggers/get_trigger_actions.ts deleted file mode 100644 index 37d7d5534c8c1..0000000000000 --- a/src/plugins/ui_actions/public/triggers/get_trigger_actions.ts +++ /dev/null @@ -1,29 +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 { UiActionsApiPure } from '../types'; -import { Action } from '../actions'; - -export const getTriggerActions: UiActionsApiPure['getTriggerActions'] = ({ - api, - actions, -}) => id => { - const trigger = api.getTrigger!(id); - return trigger.actionIds.map(actionId => actions.get(actionId)).filter(Boolean) as Action[]; -}; diff --git a/src/plugins/ui_actions/public/triggers/get_trigger_compatible_actions.ts b/src/plugins/ui_actions/public/triggers/get_trigger_compatible_actions.ts deleted file mode 100644 index 8be0db7561db9..0000000000000 --- a/src/plugins/ui_actions/public/triggers/get_trigger_compatible_actions.ts +++ /dev/null @@ -1,32 +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 { UiActionsApiPure } from '../types'; -import { Action } from '../actions/action'; - -export const getTriggerCompatibleActions: UiActionsApiPure['getTriggerCompatibleActions'] = ({ - api, -}) => async (triggerId, context) => { - const actions = api.getTriggerActions!(triggerId); - const isCompatibles = await Promise.all(actions.map(action => action.isCompatible(context))); - return actions.reduce( - (acc, action, i) => (isCompatibles[i] ? [...acc, action] : acc), - [] - ); -}; diff --git a/src/plugins/ui_actions/public/triggers/index.ts b/src/plugins/ui_actions/public/triggers/index.ts index 3006a5428f45e..a34c6eda61ba0 100644 --- a/src/plugins/ui_actions/public/triggers/index.ts +++ b/src/plugins/ui_actions/public/triggers/index.ts @@ -17,4 +17,4 @@ * under the License. */ -export { IncompatibleActionError } from './incompatible_action_error'; +export { Trigger } from './trigger'; diff --git a/src/plugins/ui_actions/public/triggers/register_trigger.ts b/src/plugins/ui_actions/public/triggers/register_trigger.ts deleted file mode 100644 index c9a7bb211d05a..0000000000000 --- a/src/plugins/ui_actions/public/triggers/register_trigger.ts +++ /dev/null @@ -1,28 +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 { UiActionsApiPure } from '../types'; - -export const registerTrigger: UiActionsApiPure['registerTrigger'] = ({ triggers }) => trigger => { - if (triggers.has(trigger.id)) { - throw new Error(`Trigger [trigger.id = ${trigger.id}] already registered.`); - } - - triggers.set(trigger.id, trigger); -}; diff --git a/src/plugins/ui_actions/public/triggers/registry.test.ts b/src/plugins/ui_actions/public/triggers/registry.test.ts deleted file mode 100644 index 6edb2b19a95e4..0000000000000 --- a/src/plugins/ui_actions/public/triggers/registry.test.ts +++ /dev/null @@ -1,149 +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 '../api'; -import { createDeps } from '../tests/helpers'; - -const HELLO_WORLD_ACTION_ID = 'HELLO_WORLD_ACTION_ID'; - -test('can register trigger', () => { - const deps = createDeps(); - const { api } = createApi(deps); - - api.registerTrigger({ - actionIds: [], - description: 'foo', - id: 'bar', - title: 'baz', - }); - - expect(deps.triggers.get('bar')).toEqual({ - actionIds: [], - description: 'foo', - id: 'bar', - title: 'baz', - }); -}); - -test('can register action', () => { - const deps = createDeps(); - const { api } = createApi(deps); - - api.registerAction({ - id: HELLO_WORLD_ACTION_ID, - order: 13, - } as any); - - expect(deps.actions.get(HELLO_WORLD_ACTION_ID)).toMatchObject({ - id: HELLO_WORLD_ACTION_ID, - order: 13, - }); -}); - -test('can attach an action to a trigger', () => { - const deps = createDeps(); - const { api } = createApi(deps); - const trigger = { - id: 'MY-TRIGGER', - actionIds: [], - }; - const action = { - id: HELLO_WORLD_ACTION_ID, - order: 25, - } as any; - - expect(trigger.actionIds).toEqual([]); - - api.registerTrigger(trigger); - api.registerAction(action); - api.attachAction('MY-TRIGGER', HELLO_WORLD_ACTION_ID); - - expect(trigger.actionIds).toEqual([HELLO_WORLD_ACTION_ID]); -}); - -test('can detach an action to a trigger', () => { - const deps = createDeps(); - const { api } = createApi(deps); - const trigger = { - id: 'MY-TRIGGER', - actionIds: [], - }; - const action = { - id: HELLO_WORLD_ACTION_ID, - order: 25, - } as any; - - expect(trigger.actionIds).toEqual([]); - - api.registerTrigger(trigger); - api.registerAction(action); - api.attachAction('MY-TRIGGER', HELLO_WORLD_ACTION_ID); - api.detachAction('MY-TRIGGER', HELLO_WORLD_ACTION_ID); - - expect(trigger.actionIds).toEqual([]); -}); - -test('detaching an invalid action from a trigger throws an error', async () => { - const { api } = createApi({ actions: new Map(), triggers: new Map() }); - const action = { - id: HELLO_WORLD_ACTION_ID, - order: 25, - } as any; - - api.registerAction(action); - expect(() => api.detachAction('i do not exist', HELLO_WORLD_ACTION_ID)).toThrowError( - 'No trigger [triggerId = i do not exist] exists, for detaching action [actionId = HELLO_WORLD_ACTION_ID].' - ); -}); - -test('attaching an invalid action to a trigger throws an error', async () => { - const { api } = createApi({ actions: new Map(), triggers: new Map() }); - const action = { - id: HELLO_WORLD_ACTION_ID, - order: 25, - } as any; - - api.registerAction(action); - expect(() => api.attachAction('i do not exist', HELLO_WORLD_ACTION_ID)).toThrowError( - 'No trigger [triggerId = i do not exist] exists, for attaching action [actionId = HELLO_WORLD_ACTION_ID].' - ); -}); - -test('cannot register another action with the same ID', async () => { - const { api } = createApi({ actions: new Map(), triggers: new Map() }); - const action = { - id: HELLO_WORLD_ACTION_ID, - order: 25, - } as any; - - api.registerAction(action); - expect(() => api.registerAction(action)).toThrowError( - 'Action [action.id = HELLO_WORLD_ACTION_ID] already registered.' - ); -}); - -test('cannot register another trigger with the same ID', async () => { - const { api } = createApi({ actions: new Map(), triggers: new Map() }); - const trigger = { id: 'MY-TRIGGER' } as any; - - api.registerTrigger(trigger); - expect(() => api.registerTrigger(trigger)).toThrowError( - 'Trigger [trigger.id = MY-TRIGGER] already registered.' - ); -}); diff --git a/src/plugins/ui_actions/public/triggers/trigger.ts b/src/plugins/ui_actions/public/triggers/trigger.ts index 3db11953053d5..ba83f5619e250 100644 --- a/src/plugins/ui_actions/public/triggers/trigger.ts +++ b/src/plugins/ui_actions/public/triggers/trigger.ts @@ -21,5 +21,4 @@ export interface Trigger { id: string; title?: string; description?: string; - actionIds: string[]; } diff --git a/src/plugins/ui_actions/public/types.ts b/src/plugins/ui_actions/public/types.ts index ed4728342b751..9bd6ffdef2af3 100644 --- a/src/plugins/ui_actions/public/types.ts +++ b/src/plugins/ui_actions/public/types.ts @@ -20,39 +20,6 @@ import { Action } from './actions/action'; import { Trigger } from './triggers/trigger'; -export { Action } from './actions'; -export { Trigger } from './triggers/trigger'; - -export type ExecuteTriggerActions = (triggerId: string, actionContext: A) => Promise; - -export type GetActionsCompatibleWithTrigger = ( - triggerId: string, - context: C -) => Promise; - -export interface UiActionsApi { - attachAction: (triggerId: string, actionId: string) => void; - detachAction: (triggerId: string, actionId: string) => void; - executeTriggerActions: ExecuteTriggerActions; - getTrigger: (id: string) => Trigger; - getTriggerActions: (id: string) => Action[]; - getTriggerCompatibleActions: (triggerId: string, context: C) => Promise>>; - registerAction: (action: Action) => void; - registerTrigger: (trigger: Trigger) => void; -} - -export interface UiActionsDependencies { - actions: ActionRegistry; - triggers: TriggerRegistry; -} - -export interface UiActionsDependenciesInternal extends UiActionsDependencies { - api: Readonly>; -} - -export type UiActionsApiPure = { - [K in keyof UiActionsApi]: (deps: UiActionsDependenciesInternal) => UiActionsApi[K]; -}; - export type TriggerRegistry = Map; export type ActionRegistry = Map; +export type TriggerToActionsRegistry = Map; From 85d737c401d492a715efcdf533efbd21d014d9c0 Mon Sep 17 00:00:00 2001 From: Vadim Dalecky Date: Mon, 17 Feb 2020 15:02:21 +0100 Subject: [PATCH 14/21] ExecutionContract (#57559) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 add ExecutionContract class * test: 💍 add Execution and Executor tests * feat: 🎸 add .execute() method to ExpressionsService * refactor: 💡 replace ExpressionDataHandler by ExecutionContract * fix: 🐛 fix TypeScript typecheck errors * docs: ✏️ add JSDocs to ExecutionContract * refactor: 💡 make .ast and .expresions both optional * test: 💍 fix test * test: 💍 fix a test * test: 💍 fix interpreter functional tests --- .../common/execution/execution.test.ts | 37 ++++- .../expressions/common/execution/execution.ts | 37 ++++- .../execution/execution_contract.test.ts | 140 ++++++++++++++++++ .../common/execution/execution_contract.ts | 90 +++++++++++ .../expressions/common/execution/index.ts | 1 + .../executor/executor.execution.test.ts | 59 ++++++++ .../common/executor/executor.test.ts | 4 +- .../expressions/common/executor/executor.ts | 24 ++- .../common/service/expressions_services.ts | 24 ++- .../expressions/public/execute.test.ts | 100 ------------- src/plugins/expressions/public/execute.ts | 138 ----------------- src/plugins/expressions/public/index.ts | 2 +- src/plugins/expressions/public/loader.test.ts | 127 ++++------------ src/plugins/expressions/public/loader.ts | 42 +++--- src/plugins/expressions/public/mocks.tsx | 1 - src/plugins/expressions/public/plugin.test.ts | 9 ++ src/plugins/expressions/public/plugin.ts | 7 +- src/plugins/expressions/public/services.ts | 5 + .../public/np_ready/app/components/main.tsx | 11 +- .../public/np_ready/types.ts | 9 +- .../test_suites/run_pipeline/basic.ts | 2 +- .../test_suites/run_pipeline/helpers.ts | 6 +- 22 files changed, 477 insertions(+), 398 deletions(-) create mode 100644 src/plugins/expressions/common/execution/execution_contract.test.ts create mode 100644 src/plugins/expressions/common/execution/execution_contract.ts create mode 100644 src/plugins/expressions/common/executor/executor.execution.test.ts delete mode 100644 src/plugins/expressions/public/execute.test.ts delete mode 100644 src/plugins/expressions/public/execute.ts diff --git a/src/plugins/expressions/common/execution/execution.test.ts b/src/plugins/expressions/common/execution/execution.test.ts index 3937bd309327d..eeb1ed80e8d0d 100644 --- a/src/plugins/expressions/common/execution/execution.test.ts +++ b/src/plugins/expressions/common/execution/execution.test.ts @@ -21,6 +21,7 @@ import { Execution } from './execution'; import { parseExpression } from '../ast'; import { createUnitTestExecutor } from '../test_helpers'; import { ExpressionFunctionDefinition } from '../../public'; +import { ExecutionContract } from './execution_contract'; const createExecution = ( expression: string = 'foo bar=123', @@ -48,7 +49,7 @@ const run = async ( describe('Execution', () => { test('can instantiate', () => { const execution = createExecution('foo bar=123'); - expect(execution.params.ast.chain[0].arguments.bar).toEqual([123]); + expect(execution.state.get().ast.chain[0].arguments.bar).toEqual([123]); }); test('initial input is null at creation', () => { @@ -127,6 +128,40 @@ describe('Execution', () => { }); }); + describe('.expression', () => { + test('uses expression passed in to constructor', () => { + const expression = 'add val="1"'; + const executor = createUnitTestExecutor(); + const execution = new Execution({ + executor, + expression, + }); + expect(execution.expression).toBe(expression); + }); + + test('generates expression from AST if not passed to constructor', () => { + const expression = 'add val="1"'; + const executor = createUnitTestExecutor(); + const execution = new Execution({ + ast: parseExpression(expression), + executor, + }); + expect(execution.expression).toBe(expression); + }); + }); + + describe('.contract', () => { + test('is instance of ExecutionContract', () => { + const execution = createExecution('add val=1'); + expect(execution.contract).toBeInstanceOf(ExecutionContract); + }); + + test('execution returns the same expression string', () => { + const execution = createExecution('add val=1'); + expect(execution.expression).toBe(execution.contract.getExpression()); + }); + }); + describe('execution context', () => { test('context.variables is an object', async () => { const { result } = (await run('introspectContext key="variables"')) as any; diff --git a/src/plugins/expressions/common/execution/execution.ts b/src/plugins/expressions/common/execution/execution.ts index 7f4efafc13de8..2a272e187cffc 100644 --- a/src/plugins/expressions/common/execution/execution.ts +++ b/src/plugins/expressions/common/execution/execution.ts @@ -24,17 +24,25 @@ import { createError } from '../util'; import { Defer } from '../../../kibana_utils/common'; import { RequestAdapter, DataAdapter } from '../../../inspector/common'; import { isExpressionValueError } from '../expression_types/specs/error'; -import { ExpressionAstExpression, ExpressionAstFunction, parse } from '../ast'; +import { + ExpressionAstExpression, + ExpressionAstFunction, + parse, + formatExpression, + parseExpression, +} from '../ast'; import { ExecutionContext, DefaultInspectorAdapters } from './types'; import { getType } from '../expression_types'; import { ArgumentType, ExpressionFunction } from '../expression_functions'; import { getByAlias } from '../util/get_by_alias'; +import { ExecutionContract } from './execution_contract'; export interface ExecutionParams< ExtraContext extends Record = Record > { executor: Executor; - ast: ExpressionAstExpression; + ast?: ExpressionAstExpression; + expression?: string; context?: ExtraContext; } @@ -85,6 +93,19 @@ export class Execution< */ private readonly firstResultFuture = new Defer(); + /** + * Contract is a public representation of `Execution` instances. Contract we + * can return to other plugins for their consumption. + */ + public readonly contract: ExecutionContract< + ExtraContext, + Input, + Output, + InspectorAdapters + > = new ExecutionContract(this); + + public readonly expression: string; + public get result(): Promise { return this.firstResultFuture.promise; } @@ -94,7 +115,17 @@ export class Execution< } constructor(public readonly params: ExecutionParams) { - const { executor, ast } = params; + const { executor } = params; + + if (!params.ast && !params.expression) { + throw new TypeError('Execution params should contain at least .ast or .expression key.'); + } else if (params.ast && params.expression) { + throw new TypeError('Execution params cannot contain both .ast and .expression key.'); + } + + this.expression = params.expression || formatExpression(params.ast!); + const ast = params.ast || parseExpression(this.expression); + this.state = createExecutionContainer({ ...executor.state.get(), state: 'not-started', diff --git a/src/plugins/expressions/common/execution/execution_contract.test.ts b/src/plugins/expressions/common/execution/execution_contract.test.ts new file mode 100644 index 0000000000000..c33f8a1a0f36e --- /dev/null +++ b/src/plugins/expressions/common/execution/execution_contract.test.ts @@ -0,0 +1,140 @@ +/* + * 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 { Execution } from './execution'; +import { parseExpression } from '../ast'; +import { createUnitTestExecutor } from '../test_helpers'; +import { ExecutionContract } from './execution_contract'; + +const createExecution = ( + expression: string = 'foo bar=123', + context: Record = {} +) => { + const executor = createUnitTestExecutor(); + const execution = new Execution({ + executor, + ast: parseExpression(expression), + context, + }); + return execution; +}; + +describe('ExecutionContract', () => { + test('can instantiate', () => { + const execution = createExecution('foo bar=123'); + const contract = new ExecutionContract(execution); + expect(contract).toBeInstanceOf(ExecutionContract); + }); + + test('can get the AST of expression', () => { + const execution = createExecution('foo bar=123'); + const contract = new ExecutionContract(execution); + expect(contract.getAst()).toMatchObject({ + type: 'expression', + chain: expect.any(Array), + }); + }); + + test('can get expression string', () => { + const execution = createExecution('foo bar=123'); + const contract = new ExecutionContract(execution); + expect(contract.getExpression()).toBe('foo bar=123'); + }); + + test('can cancel execution', () => { + const execution = createExecution('foo bar=123'); + const spy = jest.spyOn(execution, 'cancel'); + const contract = new ExecutionContract(execution); + + expect(spy).toHaveBeenCalledTimes(0); + contract.cancel(); + expect(spy).toHaveBeenCalledTimes(1); + }); + + test('can get inspector adapters', () => { + const execution = createExecution('foo bar=123'); + const contract = new ExecutionContract(execution); + expect(contract.inspect()).toMatchObject({ + data: expect.any(Object), + requests: expect.any(Object), + }); + }); + + test('can get error result of the expression execution', async () => { + const execution = createExecution('foo bar=123'); + const contract = new ExecutionContract(execution); + execution.start(); + + const result = await contract.getData(); + + expect(result).toMatchObject({ + type: 'error', + }); + }); + + test('can get result of the expression execution', async () => { + const execution = createExecution('var_set name="foo" value="bar" | var name="foo"'); + const contract = new ExecutionContract(execution); + execution.start(); + + const result = await contract.getData(); + + expect(result).toBe('bar'); + }); + + describe('isPending', () => { + test('is true if execution has not been started', async () => { + const execution = createExecution('var_set name="foo" value="bar" | var name="foo"'); + const contract = new ExecutionContract(execution); + expect(contract.isPending).toBe(true); + }); + + test('is true when execution just started', async () => { + const execution = createExecution('var_set name="foo" value="bar" | var name="foo"'); + const contract = new ExecutionContract(execution); + + execution.start(); + + expect(contract.isPending).toBe(true); + }); + + test('is false when execution finished successfully', async () => { + const execution = createExecution('var_set name="foo" value="bar" | var name="foo"'); + const contract = new ExecutionContract(execution); + + execution.start(); + await execution.result; + + expect(contract.isPending).toBe(false); + expect(execution.state.get().state).toBe('result'); + }); + + test('is false when execution finished with error', async () => { + const execution = createExecution('var_set name="foo" value="bar" | var name="foo"'); + const contract = new ExecutionContract(execution); + + execution.start(); + await execution.result; + execution.state.get().state = 'error'; + + expect(contract.isPending).toBe(false); + expect(execution.state.get().state).toBe('error'); + }); + }); +}); diff --git a/src/plugins/expressions/common/execution/execution_contract.ts b/src/plugins/expressions/common/execution/execution_contract.ts new file mode 100644 index 0000000000000..8c784352b9fdf --- /dev/null +++ b/src/plugins/expressions/common/execution/execution_contract.ts @@ -0,0 +1,90 @@ +/* + * 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 { Execution } from './execution'; + +/** + * `ExecutionContract` is a wrapper around `Execution` class. It provides the + * same functionality but does not expose Expressions plugin internals. + */ +export class ExecutionContract< + ExtraContext extends Record = Record, + Input = unknown, + Output = unknown, + InspectorAdapters = unknown +> { + public get isPending(): boolean { + const state = this.execution.state.get().state; + const finished = state === 'error' || state === 'result'; + return !finished; + } + + constructor( + protected readonly execution: Execution + ) {} + + /** + * Cancel the execution of the expression. This will set abort signal + * (available in execution context) to aborted state, letting expression + * functions to stop their execution. + */ + cancel = () => { + this.execution.cancel(); + }; + + /** + * Returns the final output of expression, if any error happens still + * wraps that error into `ExpressionValueError` type and returns that. + * This function never throws. + */ + getData = async () => { + try { + return await this.execution.result; + } catch (e) { + return { + type: 'error', + error: { + type: e.type, + message: e.message, + stack: e.stack, + }, + }; + } + }; + + /** + * Get string representation of the expression. Returns the original string + * if execution was started from a string. If execution was started from an + * AST this method returns a string generated from AST. + */ + getExpression = () => { + return this.execution.expression; + }; + + /** + * Get AST used to execute the expression. + */ + getAst = () => this.execution.state.get().ast; + + /** + * Get Inspector adapters provided to all functions of expression through + * execution context. + */ + inspect = () => this.execution.inspectorAdapters; +} diff --git a/src/plugins/expressions/common/execution/index.ts b/src/plugins/expressions/common/execution/index.ts index 2452b0999d23e..fd5c0244438d7 100644 --- a/src/plugins/expressions/common/execution/index.ts +++ b/src/plugins/expressions/common/execution/index.ts @@ -20,3 +20,4 @@ export * from './types'; export * from './container'; export * from './execution'; +export * from './execution_contract'; diff --git a/src/plugins/expressions/common/executor/executor.execution.test.ts b/src/plugins/expressions/common/executor/executor.execution.test.ts new file mode 100644 index 0000000000000..eec7b5c907e29 --- /dev/null +++ b/src/plugins/expressions/common/executor/executor.execution.test.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 { Executor } from './executor'; +import { parseExpression } from '../ast'; + +// eslint-disable-next-line +const { __getArgs } = require('../execution/execution'); + +jest.mock('../execution/execution', () => { + const mockedModule = { + args: undefined, + __getArgs: () => mockedModule.args, + Execution: function ExecutionMock(...args: any) { + mockedModule.args = args; + }, + }; + + return mockedModule; +}); + +describe('Executor mocked execution tests', () => { + describe('createExecution()', () => { + describe('when execution is created from string', () => { + test('passes expression string to Execution', () => { + const executor = new Executor(); + executor.createExecution('foo bar="baz"'); + + expect(__getArgs()[0].expression).toBe('foo bar="baz"'); + }); + }); + + describe('when execution is created from AST', () => { + test('does not pass in expression string', () => { + const executor = new Executor(); + const ast = parseExpression('foo bar="baz"'); + executor.createExecution(ast); + + expect(__getArgs()[0].expression).toBe(undefined); + }); + }); + }); +}); diff --git a/src/plugins/expressions/common/executor/executor.test.ts b/src/plugins/expressions/common/executor/executor.test.ts index 502728bb66403..4e43cedd18157 100644 --- a/src/plugins/expressions/common/executor/executor.test.ts +++ b/src/plugins/expressions/common/executor/executor.test.ts @@ -130,7 +130,7 @@ describe('Executor', () => { const execution = executor.createExecution('foo bar="baz"'); expect(execution).toBeInstanceOf(Execution); - expect(execution.params.ast.chain[0].function).toBe('foo'); + expect(execution.state.get().ast.chain[0].function).toBe('foo'); }); test('returns Execution object from AST', () => { @@ -139,7 +139,7 @@ describe('Executor', () => { const execution = executor.createExecution(ast); expect(execution).toBeInstanceOf(Execution); - expect(execution.params.ast.chain[0].function).toBe('foo'); + expect(execution.state.get().ast.chain[0].function).toBe('foo'); }); test('Execution inherits context from Executor', () => { diff --git a/src/plugins/expressions/common/executor/executor.ts b/src/plugins/expressions/common/executor/executor.ts index 5c27201b43fc0..24c1648a8cd0f 100644 --- a/src/plugins/expressions/common/executor/executor.ts +++ b/src/plugins/expressions/common/executor/executor.ts @@ -22,12 +22,12 @@ import { ExecutorState, ExecutorContainer } from './container'; import { createExecutorContainer } from './container'; import { AnyExpressionFunctionDefinition, ExpressionFunction } from '../expression_functions'; -import { Execution } from '../execution/execution'; +import { Execution, ExecutionParams } from '../execution/execution'; import { IRegistry } from '../types'; import { ExpressionType } from '../expression_types/expression_type'; import { AnyExpressionTypeDefinition } from '../expression_types/types'; import { getType } from '../expression_types'; -import { ExpressionAstExpression, ExpressionAstNode, parseExpression } from '../ast'; +import { ExpressionAstExpression, ExpressionAstNode } from '../ast'; import { typeSpecs } from '../expression_types/specs'; import { functionSpecs } from '../expression_functions/specs'; @@ -186,19 +186,27 @@ export class Executor = Record = Record>( + public createExecution< + ExtraContext extends Record = Record, + Input = unknown, + Output = unknown + >( ast: string | ExpressionAstExpression, context: ExtraContext = {} as ExtraContext - ): Execution { - if (typeof ast === 'string') ast = parseExpression(ast); - const execution = new Execution({ - ast, + ): Execution { + const params: ExecutionParams = { executor: this, context: { ...this.context, ...context, } as Context & ExtraContext, - }); + }; + + if (typeof ast === 'string') params.expression = ast; + else params.ast = ast; + + const execution = new Execution(params); + return execution; } } diff --git a/src/plugins/expressions/common/service/expressions_services.ts b/src/plugins/expressions/common/service/expressions_services.ts index 8543fbe0fced2..9663c05f0d7c2 100644 --- a/src/plugins/expressions/common/service/expressions_services.ts +++ b/src/plugins/expressions/common/service/expressions_services.ts @@ -20,6 +20,7 @@ import { Executor } from '../executor'; import { ExpressionRendererRegistry } from '../expression_renderers'; import { ExpressionAstExpression } from '../ast'; +import { ExecutionContract } from '../execution/execution_contract'; export type ExpressionsServiceSetup = ReturnType; export type ExpressionsServiceStart = ReturnType; @@ -117,6 +118,26 @@ export class ExpressionsService { context?: ExtraContext ): Promise => this.executor.run(ast, input, context); + /** + * Starts expression execution and immediately returns `ExecutionContract` + * instance that tracks the progress of the execution and can be used to + * interact with the execution. + */ + public readonly execute = < + Input = unknown, + Output = unknown, + ExtraContext extends Record = Record + >( + ast: string | ExpressionAstExpression, + // This any is for legacy reasons. + input: Input = { type: 'null' } as any, + context?: ExtraContext + ): ExecutionContract => { + const execution = this.executor.createExecution(ast, context); + execution.start(input); + return execution.contract; + }; + public setup() { const { executor, renderers, registerFunction, run } = this; @@ -144,7 +165,7 @@ export class ExpressionsService { } public start() { - const { executor, renderers, run } = this; + const { execute, executor, renderers, run } = this; const getFunction = executor.getFunction.bind(executor); const getFunctions = executor.getFunctions.bind(executor); @@ -154,6 +175,7 @@ export class ExpressionsService { const getTypes = executor.getTypes.bind(executor); return { + execute, getFunction, getFunctions, getRenderer, diff --git a/src/plugins/expressions/public/execute.test.ts b/src/plugins/expressions/public/execute.test.ts deleted file mode 100644 index 2f2a303bad4c4..0000000000000 --- a/src/plugins/expressions/public/execute.test.ts +++ /dev/null @@ -1,100 +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 { execute, ExpressionDataHandler } from './execute'; -import { ExpressionAstExpression, parseExpression } from '../common'; - -jest.mock('./services', () => ({ - getInterpreter: () => { - return { - interpretAst: async (expression: ExpressionAstExpression) => { - return {}; - }, - }; - }, - getNotifications: jest.fn(() => { - return { - toasts: { - addError: jest.fn(() => {}), - }, - }; - }), -})); - -describe('execute helper function', () => { - it('returns ExpressionDataHandler instance', () => { - const response = execute(''); - expect(response).toBeInstanceOf(ExpressionDataHandler); - }); -}); - -describe('ExpressionDataHandler', () => { - const expressionString = ''; - - describe('constructor', () => { - it('accepts expression string', () => { - const expressionDataHandler = new ExpressionDataHandler(expressionString, {}); - expect(expressionDataHandler.getExpression()).toEqual(expressionString); - }); - - it('accepts expression AST', () => { - const expressionAST = parseExpression(expressionString) as ExpressionAstExpression; - const expressionDataHandler = new ExpressionDataHandler(expressionAST, {}); - expect(expressionDataHandler.getExpression()).toEqual(expressionString); - expect(expressionDataHandler.getAst()).toEqual(expressionAST); - }); - - it('allows passing in context', () => { - const expressionDataHandler = new ExpressionDataHandler(expressionString, { - context: { test: 'hello' }, - }); - expect(expressionDataHandler.getExpression()).toEqual(expressionString); - }); - - it('allows passing in search context', () => { - const expressionDataHandler = new ExpressionDataHandler(expressionString, { - searchContext: { filters: [] }, - }); - expect(expressionDataHandler.getExpression()).toEqual(expressionString); - }); - }); - - describe('getData()', () => { - it('returns a promise', () => { - const expressionDataHandler = new ExpressionDataHandler(expressionString, {}); - expect(expressionDataHandler.getData()).toBeInstanceOf(Promise); - }); - - it('promise resolves with data', async () => { - const expressionDataHandler = new ExpressionDataHandler(expressionString, {}); - expect(await expressionDataHandler.getData()).toEqual({}); - }); - }); - - it('cancel() aborts request', () => { - const expressionDataHandler = new ExpressionDataHandler(expressionString, {}); - expressionDataHandler.cancel(); - }); - - it('inspect() returns correct inspector adapters', () => { - const expressionDataHandler = new ExpressionDataHandler(expressionString, {}); - expect(expressionDataHandler.inspect()).toHaveProperty('requests'); - expect(expressionDataHandler.inspect()).toHaveProperty('data'); - }); -}); diff --git a/src/plugins/expressions/public/execute.ts b/src/plugins/expressions/public/execute.ts deleted file mode 100644 index c07fb9ad0549c..0000000000000 --- a/src/plugins/expressions/public/execute.ts +++ /dev/null @@ -1,138 +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 { DataAdapter, RequestAdapter, Adapters } from '../../inspector/public'; -import { getInterpreter } from './services'; -import { IExpressionLoaderParams } from './types'; -import { - ExpressionAstExpression, - parseExpression, - formatExpression, - ExpressionValue, -} from '../common'; - -/** - * The search context describes a specific context (filters, time range and query) - * that will be applied to the expression for execution. Not every expression will - * be effected by that. You have to use special functions - * that will pick up this search context and forward it to following functions that - * understand it. - */ - -export class ExpressionDataHandler { - private abortController: AbortController; - private expression: string; - private ast: ExpressionAstExpression; - - private inspectorAdapters: Adapters; - private promise: Promise; - - public isPending: boolean = true; - constructor(expression: string | ExpressionAstExpression, params: IExpressionLoaderParams) { - if (typeof expression === 'string') { - this.expression = expression; - this.ast = parseExpression(expression); - } else { - this.ast = expression; - this.expression = formatExpression(this.ast); - } - - this.abortController = new AbortController(); - this.inspectorAdapters = params.inspectorAdapters || this.getActiveInspectorAdapters(); - - const defaultInput = { type: 'null' }; - const interpreter = getInterpreter(); - this.promise = interpreter - .interpretAst(this.ast, params.context || defaultInput, { - search: params.searchContext, - inspectorAdapters: this.inspectorAdapters, - abortSignal: this.abortController.signal, - variables: params.variables, - }) - .then( - (v: ExpressionValue) => { - this.isPending = false; - return v; - }, - () => { - this.isPending = false; - } - ) as Promise; - } - - cancel = () => { - this.abortController.abort(); - }; - - getData = async () => { - try { - return await this.promise; - } catch (e) { - return { - type: 'error', - error: { - type: e.type, - message: e.message, - stack: e.stack, - }, - }; - } - }; - - getExpression = () => { - return this.expression; - }; - - getAst = () => { - return this.ast; - }; - - inspect = () => { - return this.inspectorAdapters; - }; - - /** - * Returns an object of all inspectors for this vis object. - * This must only be called after this.type has properly be initialized, - * since we need to read out data from the the vis type to check which - * inspectors are available. - */ - private getActiveInspectorAdapters = (): Adapters => { - const adapters: Adapters = {}; - - // Add the requests inspector adapters if the vis type explicitly requested it via - // inspectorAdapters.requests: true in its definition or if it's using the courier - // request handler, since that will automatically log its requests. - adapters.requests = new RequestAdapter(); - - // Add the data inspector adapter if the vis type requested it or if the - // vis is using courier, since we know that courier supports logging - // its data. - adapters.data = new DataAdapter(); - - return adapters; - }; -} - -export function execute( - expression: string | ExpressionAstExpression, - params: IExpressionLoaderParams = {} -): ExpressionDataHandler { - return new ExpressionDataHandler(expression, params); -} diff --git a/src/plugins/expressions/public/index.ts b/src/plugins/expressions/public/index.ts index 5f64c11f4efe6..06dd951cd5410 100644 --- a/src/plugins/expressions/public/index.ts +++ b/src/plugins/expressions/public/index.ts @@ -37,7 +37,6 @@ export { ReactExpressionRendererProps, ReactExpressionRendererType, } from './react_expression_renderer'; -export { ExpressionDataHandler } from './execute'; export { ExpressionRenderHandler } from './render'; export { AnyExpressionFunctionDefinition, @@ -48,6 +47,7 @@ export { DatatableColumnType, DatatableRow, Execution, + ExecutionContract, ExecutionContainer, ExecutionContext, ExecutionParams, diff --git a/src/plugins/expressions/public/loader.test.ts b/src/plugins/expressions/public/loader.test.ts index 480434244d6f5..e07a22a5e1d60 100644 --- a/src/plugins/expressions/public/loader.test.ts +++ b/src/plugins/expressions/public/loader.test.ts @@ -19,10 +19,12 @@ import { first, skip, toArray } from 'rxjs/operators'; import { loader, ExpressionLoader } from './loader'; -import { ExpressionDataHandler } from './execute'; import { Observable } from 'rxjs'; import { ExpressionAstExpression, parseExpression, IInterpreterRenderHandlers } from '../common'; +// eslint-disable-next-line +const { __getLastExecution } = require('./services'); + const element: HTMLElement = null as any; jest.mock('./services', () => { @@ -33,7 +35,13 @@ jest.mock('./services', () => { }, }, }; - return { + + // eslint-disable-next-line + const service = new (require('../common/service/expressions_services').ExpressionsService as any)(); + + const moduleMock = { + __execution: undefined, + __getLastExecution: () => moduleMock.__execution, getInterpreter: () => { return { interpretAst: async (expression: ExpressionAstExpression) => { @@ -51,17 +59,19 @@ jest.mock('./services', () => { }, }; }), + getExpressionsService: () => service, }; -}); -jest.mock('./execute', () => { - const actual = jest.requireActual('./execute'); - return { - ExpressionDataHandler: jest - .fn() - .mockImplementation((...args) => new actual.ExpressionDataHandler(...args)), - execute: jest.fn().mockReturnValue(actual.execute), + const execute = service.execute; + service.execute = (...args: any) => { + const execution = execute(...args); + jest.spyOn(execution, 'getData'); + jest.spyOn(execution, 'cancel'); + moduleMock.__execution = execution; + return execution; }; + + return moduleMock; }); describe('execute helper function', () => { @@ -97,9 +107,9 @@ describe('ExpressionLoader', () => { }); it('emits on $data when data is available', async () => { - const expressionLoader = new ExpressionLoader(element, expressionString, {}); + const expressionLoader = new ExpressionLoader(element, 'var foo', { variables: { foo: 123 } }); const response = await expressionLoader.data$.pipe(first()).toPromise(); - expect(response).toEqual({ type: 'render', as: 'test' }); + expect(response).toBe(123); }); it('emits on loading$ on initial load and on updates', async () => { @@ -128,94 +138,13 @@ describe('ExpressionLoader', () => { }); it('cancels the previous request when the expression is updated', () => { - const cancelMock = jest.fn(); - - (ExpressionDataHandler as jest.Mock).mockImplementationOnce(() => ({ - getData: () => true, - cancel: cancelMock, - isPending: () => true, - inspect: () => {}, - })); - - const expressionLoader = new ExpressionLoader(element, expressionString, {}); - expressionLoader.update('new', {}); - - expect(cancelMock).toHaveBeenCalledTimes(1); - }); - - it('does not send an observable message if a request was aborted', () => { - const cancelMock = jest.fn(); - - const getData = jest - .fn() - .mockResolvedValueOnce({ - type: 'error', - error: { - name: 'AbortError', - }, - }) - .mockResolvedValueOnce({ - type: 'real', - }); - - (ExpressionDataHandler as jest.Mock).mockImplementationOnce(() => ({ - getData, - cancel: cancelMock, - isPending: () => true, - inspect: () => {}, - })); - - (ExpressionDataHandler as jest.Mock).mockImplementationOnce(() => ({ - getData, - cancel: cancelMock, - isPending: () => true, - inspect: () => {}, - })); - - const expressionLoader = new ExpressionLoader(element, expressionString, {}); - - expect.assertions(2); - expressionLoader.data$.subscribe({ - next(data) { - expect(data).toEqual({ - type: 'real', - }); - }, - error() { - expect(false).toEqual('Should not be called'); - }, - }); - - expressionLoader.update('new expression', {}); - - expect(getData).toHaveBeenCalledTimes(2); - }); - - it('sends an observable error if the data fetching failed', () => { - const cancelMock = jest.fn(); - - const getData = jest.fn().mockResolvedValue('rejected'); - - (ExpressionDataHandler as jest.Mock).mockImplementationOnce(() => ({ - getData, - cancel: cancelMock, - isPending: () => true, - inspect: () => {}, - })); - - const expressionLoader = new ExpressionLoader(element, expressionString, {}); - - expect.assertions(2); - expressionLoader.data$.subscribe({ - next(data) { - expect(data).toEqual('Should not be called'); - }, - error(error) { - expect(error.message).toEqual('Could not fetch data'); - }, - }); + const expressionLoader = new ExpressionLoader(element, 'var foo', {}); + const execution = __getLastExecution(); + jest.spyOn(execution, 'cancel'); - expect(getData).toHaveBeenCalledTimes(1); + expect(execution.cancel).toHaveBeenCalledTimes(0); + expressionLoader.update('var bar', {}); + expect(execution.cancel).toHaveBeenCalledTimes(1); }); it('inspect() returns correct inspector adapters', () => { diff --git a/src/plugins/expressions/public/loader.ts b/src/plugins/expressions/public/loader.ts index 320a8469fe9e3..4600922e076fa 100644 --- a/src/plugins/expressions/public/loader.ts +++ b/src/plugins/expressions/public/loader.ts @@ -20,11 +20,11 @@ import { BehaviorSubject, Observable, Subject } from 'rxjs'; import { filter, map } from 'rxjs/operators'; import { Adapters, InspectorSession } from '../../inspector/public'; -import { ExpressionDataHandler } from './execute'; import { ExpressionRenderHandler } from './render'; import { IExpressionLoaderParams } from './types'; import { ExpressionAstExpression } from '../common'; -import { getInspector } from './services'; +import { getInspector, getExpressionsService } from './services'; +import { ExecutionContract } from '../common/execution/execution_contract'; type Data = any; @@ -35,7 +35,7 @@ export class ExpressionLoader { events$: ExpressionRenderHandler['events$']; loading$: Observable; - private dataHandler: ExpressionDataHandler | undefined; + private execution: ExecutionContract | undefined; private renderHandler: ExpressionRenderHandler; private dataSubject: Subject; private loadingSubject: Subject; @@ -93,26 +93,26 @@ export class ExpressionLoader { this.dataSubject.complete(); this.loadingSubject.complete(); this.renderHandler.destroy(); - if (this.dataHandler) { - this.dataHandler.cancel(); + if (this.execution) { + this.execution.cancel(); } } cancel() { - if (this.dataHandler) { - this.dataHandler.cancel(); + if (this.execution) { + this.execution.cancel(); } } getExpression(): string | undefined { - if (this.dataHandler) { - return this.dataHandler.getExpression(); + if (this.execution) { + return this.execution.getExpression(); } } getAst(): ExpressionAstExpression | undefined { - if (this.dataHandler) { - return this.dataHandler.getAst(); + if (this.execution) { + return this.execution.getAst(); } } @@ -130,9 +130,7 @@ export class ExpressionLoader { } inspect(): Adapters | undefined { - if (this.dataHandler) { - return this.dataHandler.inspect(); - } + return this.execution ? (this.execution.inspect() as Adapters) : undefined; } update(expression?: string | ExpressionAstExpression, params?: IExpressionLoaderParams): void { @@ -150,15 +148,19 @@ export class ExpressionLoader { expression: string | ExpressionAstExpression, params: IExpressionLoaderParams ): Promise => { - if (this.dataHandler && this.dataHandler.isPending) { - this.dataHandler.cancel(); + if (this.execution && this.execution.isPending) { + this.execution.cancel(); } this.setParams(params); - this.dataHandler = new ExpressionDataHandler(expression, params); - if (!params.inspectorAdapters) params.inspectorAdapters = this.dataHandler.inspect(); - const prevDataHandler = this.dataHandler; + this.execution = getExpressionsService().execute(expression, params.context, { + search: params.searchContext, + variables: params.variables || {}, + inspectorAdapters: params.inspectorAdapters, + }); + if (!params.inspectorAdapters) params.inspectorAdapters = this.execution.inspect() as Adapters; + const prevDataHandler = this.execution; const data = await prevDataHandler.getData(); - if (this.dataHandler !== prevDataHandler) { + if (this.execution !== prevDataHandler) { return; } this.dataSubject.next(data); diff --git a/src/plugins/expressions/public/mocks.tsx b/src/plugins/expressions/public/mocks.tsx index 70760ada83955..40ae698bc95eb 100644 --- a/src/plugins/expressions/public/mocks.tsx +++ b/src/plugins/expressions/public/mocks.tsx @@ -65,7 +65,6 @@ const createSetupContract = (): Setup => { const createStartContract = (): Start => { return { execute: jest.fn(), - ExpressionDataHandler: jest.fn(), ExpressionLoader: jest.fn(), ExpressionRenderHandler: jest.fn(), getFunction: jest.fn(), diff --git a/src/plugins/expressions/public/plugin.test.ts b/src/plugins/expressions/public/plugin.test.ts index 5437a7d21f338..fdfd583eac9de 100644 --- a/src/plugins/expressions/public/plugin.test.ts +++ b/src/plugins/expressions/public/plugin.test.ts @@ -65,6 +65,15 @@ describe('ExpressionsPublicPlugin', () => { } `); }); + + test('"kibana" function return value of type "kibana_context"', async () => { + const { doStart } = await expressionsPluginMock.createPlugin(); + const start = await doStart(); + const execution = start.execute('kibana'); + const result = await execution.getData(); + + expect((result as any).type).toBe('kibana_context'); + }); }); }); }); diff --git a/src/plugins/expressions/public/plugin.ts b/src/plugins/expressions/public/plugin.ts index 6799b1590f252..aac429b365c48 100644 --- a/src/plugins/expressions/public/plugin.ts +++ b/src/plugins/expressions/public/plugin.ts @@ -36,11 +36,11 @@ import { setInterpreter, setRenderersRegistry, setNotifications, + setExpressionsService, } from './services'; import { kibanaContext as kibanaContextFunction } from './expression_functions/kibana_context'; import { ReactExpressionRenderer } from './react_expression_renderer'; import { ExpressionLoader, loader } from './loader'; -import { ExpressionDataHandler, execute } from './execute'; import { render, ExpressionRenderHandler } from './render'; export interface ExpressionsSetupDeps { @@ -92,8 +92,6 @@ export interface ExpressionsSetup extends ExpressionsServiceSetup { } export interface ExpressionsStart extends ExpressionsServiceStart { - execute: typeof execute; - ExpressionDataHandler: typeof ExpressionDataHandler; ExpressionLoader: typeof ExpressionLoader; ExpressionRenderHandler: typeof ExpressionRenderHandler; loader: typeof loader; @@ -118,6 +116,7 @@ export class ExpressionsPublicPlugin executor.registerFunction(kibanaContextFunction()); setRenderersRegistry(renderers); + setExpressionsService(this.expressions); const expressionsSetup = expressions.setup(); @@ -180,8 +179,6 @@ export class ExpressionsPublicPlugin return { ...expressionsStart, - execute, - ExpressionDataHandler, ExpressionLoader, ExpressionRenderHandler, loader, diff --git a/src/plugins/expressions/public/services.ts b/src/plugins/expressions/public/services.ts index 75ec4826ea45a..4fdff9b151ac2 100644 --- a/src/plugins/expressions/public/services.ts +++ b/src/plugins/expressions/public/services.ts @@ -22,6 +22,7 @@ import { createKibanaUtilsCore, createGetterSetter } from '../../kibana_utils/pu import { ExpressionInterpreter } from './types'; import { Start as IInspector } from '../../inspector/public'; import { ExpressionsSetup } from './plugin'; +import { ExpressionsService } from '../common'; export const { getCoreStart, setCoreStart, savedObjects } = createKibanaUtilsCore(); @@ -37,3 +38,7 @@ export const [getNotifications, setNotifications] = createGetterSetter('Renderers registry'); + +export const [getExpressionsService, setExpressionsService] = createGetterSetter< + ExpressionsService +>('ExpressionsService'); diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/np_ready/app/components/main.tsx b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/np_ready/app/components/main.tsx index 41e466fddd11e..a50248a5b6fa3 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/np_ready/app/components/main.tsx +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/np_ready/app/components/main.tsx @@ -22,7 +22,7 @@ import { EuiPage, EuiPageBody, EuiPageContent, EuiPageContentHeader } from '@ela import { first } from 'rxjs/operators'; import { IInterpreterRenderHandlers, ExpressionValue } from 'src/plugins/expressions'; import { RequestAdapter, DataAdapter } from '../../../../../../../../src/plugins/inspector'; -import { Adapters, ExpressionRenderHandler, ExpressionDataHandler } from '../../types'; +import { Adapters, ExpressionRenderHandler } from '../../types'; import { getExpressions } from '../../services'; declare global { @@ -31,7 +31,7 @@ declare global { expressions: string, context?: ExpressionValue, initialContext?: ExpressionValue - ) => ReturnType; + ) => any; renderPipelineResponse: (context?: ExpressionValue) => Promise; } } @@ -61,12 +61,9 @@ class Main extends React.Component<{}, State> { data: new DataAdapter(), }; return getExpressions() - .execute(expression, { + .execute(expression, context || { type: 'null' }, { inspectorAdapters: adapters, - context, - // TODO: naming / typing is confusing and doesn't match here - // searchContext is also a way to set initialContext and Context can't be set to SearchContext - searchContext: initialContext as any, + search: initialContext as any, }) .getData(); }; diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/np_ready/types.ts b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/np_ready/types.ts index 6e0a93e4a3cb1..123baa1183c48 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/np_ready/types.ts +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/public/np_ready/types.ts @@ -17,12 +17,7 @@ * under the License. */ -import { - ExpressionsStart, - ExpressionRenderHandler, - ExpressionDataHandler, -} from 'src/plugins/expressions/public'; - +import { ExpressionsStart, ExpressionRenderHandler } from 'src/plugins/expressions/public'; import { Adapters } from 'src/plugins/inspector/public'; -export { ExpressionsStart, ExpressionRenderHandler, ExpressionDataHandler, Adapters }; +export { ExpressionsStart, ExpressionRenderHandler, Adapters }; diff --git a/test/interpreter_functional/test_suites/run_pipeline/basic.ts b/test/interpreter_functional/test_suites/run_pipeline/basic.ts index 77853b0bcd6a4..a2172dd2da1ba 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/basic.ts +++ b/test/interpreter_functional/test_suites/run_pipeline/basic.ts @@ -22,7 +22,7 @@ import { ExpectExpression, expectExpressionProvider } from './helpers'; import { FtrProviderContext } from '../../../functional/ftr_provider_context'; // this file showcases how to use testing utilities defined in helpers.ts together with the kbn_tp_run_pipeline -// test plugin to write autmated tests for interprete +// test plugin to write automated tests for interpreter export default function({ getService, updateBaselines, diff --git a/test/interpreter_functional/test_suites/run_pipeline/helpers.ts b/test/interpreter_functional/test_suites/run_pipeline/helpers.ts index 015c311c30aef..00693845bb266 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/helpers.ts +++ b/test/interpreter_functional/test_suites/run_pipeline/helpers.ts @@ -20,10 +20,8 @@ import expect from '@kbn/expect'; import { ExpressionValue } from 'src/plugins/expressions'; import { FtrProviderContext } from '../../../functional/ftr_provider_context'; -import { ExpressionDataHandler } from '../../plugins/kbn_tp_run_pipeline/public/np_ready/types'; -type UnWrapPromise = T extends Promise ? U : T; -export type ExpressionResult = UnWrapPromise>; +export type ExpressionResult = any; export type ExpectExpression = ( name: string, @@ -112,7 +110,7 @@ export function expectExpressionProvider({ if (!_currentContext.type) _currentContext.type = 'null'; return window .runPipeline(_expression, _currentContext, _initialContext) - .then(expressionResult => { + .then((expressionResult: any) => { done(expressionResult); return expressionResult; }); From d21d33d0b68bea3c45e49491fd4ee5671a00b3c7 Mon Sep 17 00:00:00 2001 From: Vadim Dalecky Date: Mon, 17 Feb 2020 15:25:17 +0100 Subject: [PATCH 15/21] =?UTF-8?q?fix:=20=F0=9F=90=9B=20don't=20cast=20to?= =?UTF-8?q?=20any=20(#57799)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EUI 19.0 was merged into Kibana which supports React elements as context menu items, so we don't need to cast to any here anymore. --- .../public/context_menu/build_eui_context_menu_panels.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx b/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx index 7b80a8ea830c0..3dce2c1f4c257 100644 --- a/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx +++ b/src/plugins/ui_actions/public/context_menu/build_eui_context_menu_panels.tsx @@ -101,10 +101,9 @@ function convertPanelActionToContextMenuItem({ }): EuiContextMenuPanelItemDescriptor { const menuPanelItem: EuiContextMenuPanelItemDescriptor = { name: action.MenuItem - ? // Cast to `any` because `name` typed to string. - (React.createElement(uiToReactComponent(action.MenuItem), { + ? React.createElement(uiToReactComponent(action.MenuItem), { context: actionContext, - }) as any) + }) : action.getDisplayName(actionContext), icon: action.getIconType(actionContext), panel: _.get(action, 'childContextMenuPanel.id'), From c31c7ee4c7b20eee566fd3d915620a0ce86416d1 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Mon, 17 Feb 2020 15:06:42 +0000 Subject: [PATCH 16/21] [ML] Adding get buckets endpoint wrapper (#57752) * [ML] Adding results buckets endpoint wrapper * removing unnecessary spread operator * correcting timstamp format in api doc Co-authored-by: Elastic Machine --- .../ml/server/client/elasticsearch_ml.js | 25 ++++++ .../ml/server/routes/anomaly_detectors.ts | 76 +++++++++++++++---- .../ml/server/routes/data_frame_analytics.ts | 20 ++--- 3 files changed, 98 insertions(+), 23 deletions(-) diff --git a/x-pack/legacy/plugins/ml/server/client/elasticsearch_ml.js b/x-pack/legacy/plugins/ml/server/client/elasticsearch_ml.js index cf13d329182ba..9317d3c6c3e07 100644 --- a/x-pack/legacy/plugins/ml/server/client/elasticsearch_ml.js +++ b/x-pack/legacy/plugins/ml/server/client/elasticsearch_ml.js @@ -450,6 +450,31 @@ export const elasticsearchJsPlugin = (Client, config, components) => { method: 'POST', }); + ml.buckets = ca({ + urls: [ + { + fmt: '/_ml/anomaly_detectors/<%=jobId%>/results/buckets', + req: { + jobId: { + type: 'string', + }, + }, + }, + { + fmt: '/_ml/anomaly_detectors/<%=jobId%>/results/buckets/<%=timestamp%>', + req: { + jobId: { + type: 'string', + }, + timestamp: { + type: 'string', + }, + }, + }, + ], + method: 'POST', + }); + ml.overallBuckets = ca({ url: { fmt: '/_ml/anomaly_detectors/<%=jobId%>/results/overall_buckets', diff --git a/x-pack/legacy/plugins/ml/server/routes/anomaly_detectors.ts b/x-pack/legacy/plugins/ml/server/routes/anomaly_detectors.ts index 64af1f67bce29..927646e4f0acc 100644 --- a/x-pack/legacy/plugins/ml/server/routes/anomaly_detectors.ts +++ b/x-pack/legacy/plugins/ml/server/routes/anomaly_detectors.ts @@ -36,7 +36,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.jobs'); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -67,7 +67,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { const { jobId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.jobs', { jobId }); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -94,7 +94,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.jobStats'); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -125,7 +125,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { const { jobId } = request.params; const results = await context.ml!.mlClient.callAsCurrentUser('ml.jobStats', { jobId }); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -160,7 +160,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { body: request.body, }); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -195,7 +195,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { body: request.body, }); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -228,7 +228,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { jobId, }); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -265,7 +265,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { } const results = await context.ml!.mlClient.callAsCurrentUser('ml.closeJob', options); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -302,7 +302,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { } const results = await context.ml!.mlClient.callAsCurrentUser('ml.deleteJob', options); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -332,7 +332,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { body: request.body, }); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -368,7 +368,57 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { duration, }); return response.ok({ - body: { ...results }, + body: results, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup AnomalyDetectors + * + * @api {post} /api/ml/anomaly_detectors/:jobId/results/buckets Obtain bucket scores for the specified job ID + * @apiName GetOverallBuckets + * @apiDescription The get buckets API presents a chronological view of the records, grouped by bucket. + * + * @apiParam {String} jobId Job ID. + * @apiParam {String} timestamp. + * + * @apiSuccess {Number} count + * @apiSuccess {Object[]} buckets + */ + router.post( + { + path: '/api/ml/anomaly_detectors/{jobId}/results/buckets/{timestamp?}', + validate: { + params: schema.object({ + jobId: schema.string(), + timestamp: schema.maybe(schema.string()), + }), + body: schema.object({ + anomaly_score: schema.maybe(schema.number()), + desc: schema.maybe(schema.boolean()), + end: schema.maybe(schema.string()), + exclude_interim: schema.maybe(schema.boolean()), + expand: schema.maybe(schema.boolean()), + 'page.from': schema.maybe(schema.number()), + 'page.size': schema.maybe(schema.number()), + sort: schema.maybe(schema.string()), + start: schema.maybe(schema.string()), + }), + }, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const results = await context.ml!.mlClient.callAsCurrentUser('ml.buckets', { + jobId: request.params.jobId, + timestamp: request.params.timestamp, + ...request.body, + }); + return response.ok({ + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -413,7 +463,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { end: request.body.end, }); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -449,7 +499,7 @@ export function jobRoutes({ xpackMainPlugin, router }: RouteInitialization) { }; const results = await context.ml!.mlClient.callAsCurrentUser('ml.categories', options); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); diff --git a/x-pack/legacy/plugins/ml/server/routes/data_frame_analytics.ts b/x-pack/legacy/plugins/ml/server/routes/data_frame_analytics.ts index f134820adbb48..6541fa541a59f 100644 --- a/x-pack/legacy/plugins/ml/server/routes/data_frame_analytics.ts +++ b/x-pack/legacy/plugins/ml/server/routes/data_frame_analytics.ts @@ -40,7 +40,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti try { const results = await context.ml!.mlClient.callAsCurrentUser('ml.getDataFrameAnalytics'); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -71,7 +71,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti analyticsId, }); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -97,7 +97,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti 'ml.getDataFrameAnalyticsStats' ); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -131,7 +131,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti } ); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -170,7 +170,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti } ); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -201,7 +201,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti } ); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -241,7 +241,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti } ); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -277,7 +277,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti } ); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -310,7 +310,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti analyticsId, }); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); @@ -353,7 +353,7 @@ export function dataFrameAnalyticsRoutes({ xpackMainPlugin, router }: RouteIniti options ); return response.ok({ - body: { ...results }, + body: results, }); } catch (e) { return response.customError(wrapError(e)); From 3c51fb0314799365bfe641adc7423d34e81f0d3c Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 18 Feb 2020 07:16:40 +0000 Subject: [PATCH 17/21] [ML] File data viz fix index pattern warning after index change (#57807) --- .../file_based/components/import_view/import_view.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js index bb95d3e420d2a..beb5918e277ae 100644 --- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js +++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/import_view/import_view.js @@ -325,9 +325,17 @@ export class ImportView extends Component { onIndexChange = e => { const name = e.target.value; + const { indexNames, indexPattern, indexPatternNames } = this.state; + this.setState({ index: name, - indexNameError: isIndexNameValid(name, this.state.indexNames), + indexNameError: isIndexNameValid(name, indexNames), + // if index pattern has been altered, check that it still matches the inputted index + ...(indexPattern === '' + ? {} + : { + indexPatternNameError: isIndexPatternNameValid(indexPattern, indexPatternNames, name), + }), }); }; From 446fda62f20af07d15f9a39cceebeac9f406ffcd Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Tue, 18 Feb 2020 08:25:14 +0000 Subject: [PATCH 18/21] [jenkins] Notify GH Checks for the apm-ui e2e pipeline (#52900) --- .ci/end2end.groovy | 27 +++++++++++++++++-- .../plugins/apm/cypress/ci/kibana.dev.yml | 3 +++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/.ci/end2end.groovy b/.ci/end2end.groovy index 5cf6efe324ac3..38fed4aca19dc 100644 --- a/.ci/end2end.groovy +++ b/.ci/end2end.groovy @@ -25,7 +25,7 @@ pipeline { durabilityHint('PERFORMANCE_OPTIMIZED') } triggers { - issueCommentTrigger('(?i).*jenkins\\W+run\\W+(?:the\\W+)?e2e(?:\\W+please)?.*') + issueCommentTrigger('(?i)(retest|.*jenkins\\W+run\\W+(?:the\\W+)?e2e?.*)') } parameters { booleanParam(name: 'FORCE', defaultValue: false, description: 'Whether to force the run.') @@ -60,8 +60,14 @@ pipeline { } } steps { + notifyStatus('Starting services', 'PENDING') dir("${APM_ITS}"){ - sh './scripts/compose.py start master --no-kibana --no-xpack-secure' + sh './scripts/compose.py start master --no-kibana' + } + } + post { + unsuccessful { + notifyStatus('Environmental issue', 'FAILURE') } } } @@ -77,10 +83,16 @@ pipeline { JENKINS_NODE_COOKIE = 'dontKillMe' } steps { + notifyStatus('Preparing kibana', 'PENDING') dir("${BASE_DIR}"){ sh script: "${CYPRESS_DIR}/ci/prepare-kibana.sh" } } + post { + unsuccessful { + notifyStatus('Kibana warm up failed', 'FAILURE') + } + } } stage('Smoke Tests'){ options { skipDefaultCheckout() } @@ -91,6 +103,7 @@ pipeline { } } steps{ + notifyStatus('Running smoke tests', 'PENDING') dir("${BASE_DIR}"){ sh ''' jobs -l @@ -112,6 +125,12 @@ pipeline { archiveArtifacts(allowEmptyArchive: false, artifacts: 'apm-its.log') } } + unsuccessful { + notifyStatus('Test failures', 'FAILURE') + } + success { + notifyStatus('Tests passed', 'SUCCESS') + } } } } @@ -123,3 +142,7 @@ pipeline { } } } + +def notifyStatus(String description, String status) { + withGithubNotify.notify('end2end-for-apm-ui', description, status, getBlueoceanDisplayURL()) +} diff --git a/x-pack/legacy/plugins/apm/cypress/ci/kibana.dev.yml b/x-pack/legacy/plugins/apm/cypress/ci/kibana.dev.yml index 3082391f23a15..db57db9a1abe9 100644 --- a/x-pack/legacy/plugins/apm/cypress/ci/kibana.dev.yml +++ b/x-pack/legacy/plugins/apm/cypress/ci/kibana.dev.yml @@ -2,3 +2,6 @@ # Disabled plugins ######################## logging.verbose: true +elasticsearch.username: "kibana_system_user" +elasticsearch.password: "changeme" +xpack.security.encryptionKey: "something_at_least_32_characters" From 66e685b4a80e671e0ce840bc7e98b1c944ecdd61 Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Tue, 18 Feb 2020 10:03:43 +0100 Subject: [PATCH 19/21] refactors 'flyout-button' tests (#57572) Co-authored-by: Elastic Machine --- .../fields_browser/fields_browser.spec.ts | 8 ++--- .../smoke_tests/inspect/inspect.spec.ts | 2 +- .../timeline/data_providers.spec.ts | 3 +- .../timeline/flyout_button.spec.ts | 30 +++++++------------ .../plugins/siem/cypress/screens/siem_main.ts | 9 ++++++ .../siem/cypress/screens/timeline/main.ts | 5 ++++ .../plugins/siem/cypress/tasks/siem_main.ts | 20 +++++++++++++ .../siem/cypress/tasks/timeline/main.ts | 5 ---- 8 files changed, 50 insertions(+), 32 deletions(-) create mode 100644 x-pack/legacy/plugins/siem/cypress/screens/siem_main.ts create mode 100644 x-pack/legacy/plugins/siem/cypress/tasks/siem_main.ts diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/fields_browser/fields_browser.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/fields_browser/fields_browser.spec.ts index 2889d78891a06..6e8ef93a54016 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/fields_browser/fields_browser.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/fields_browser/fields_browser.spec.ts @@ -22,11 +22,9 @@ import { FIELDS_BROWSER_HEADER_HOST_GEO_CONTINENT_NAME_HEADER, } from '../../../screens/timeline/fields_browser'; -import { - openTimeline, - populateTimeline, - openTimelineFieldsBrowser, -} from '../../../tasks/timeline/main'; +import { populateTimeline, openTimelineFieldsBrowser } from '../../../tasks/timeline/main'; + +import { openTimeline } from '../../../tasks/siem_main'; import { clearFieldsBrowser, diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/inspect/inspect.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/inspect/inspect.spec.ts index e7411aba11af5..1555470f5eee7 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/inspect/inspect.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/inspect/inspect.spec.ts @@ -12,10 +12,10 @@ import { } from '../../../screens/inspect'; import { executeTimelineKQL, - openTimeline, openTimelineSettings, openTimelineInspectButton, } from '../../../tasks/timeline/main'; +import { openTimeline } from '../../../tasks/siem_main'; import { DEFAULT_TIMEOUT, loginAndWaitForPage } from '../../../tasks/login'; import { closesModal, openStatsAndTables } from '../../../tasks/inspect'; diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/data_providers.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/data_providers.spec.ts index 3d251c1c6bcac..c3fedfb06939b 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/data_providers.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/data_providers.spec.ts @@ -13,7 +13,8 @@ import { } from '../../../tasks/hosts/all_hosts'; import { HOSTS_NAMES } from '../../../screens/hosts/all_hosts'; import { DEFAULT_TIMEOUT, loginAndWaitForPage } from '../../../tasks/login'; -import { openTimeline, createNewTimeline } from '../../../tasks/timeline/main'; +import { createNewTimeline } from '../../../tasks/timeline/main'; +import { openTimeline } from '../../../tasks/siem_main'; import { TIMELINE_DATA_PROVIDERS_EMPTY, TIMELINE_DATA_PROVIDERS, diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/flyout_button.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/flyout_button.spec.ts index 63fe56371a4cd..b7faaaac1c06c 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/flyout_button.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/flyout_button.spec.ts @@ -4,44 +4,34 @@ * you may not use this file except in compliance with the Elastic License. */ +import { HOSTS_PAGE } from '../../../urls/navigation'; +import { waitForAllHostsToBeLoaded, dragFirstHostToTimeline } from '../../../tasks/hosts/all_hosts'; +import { loginAndWaitForPage } from '../../../tasks/login'; +import { openTimelineIfClosed, openTimeline } from '../../../tasks/siem_main'; import { TIMELINE_FLYOUT_BODY, TIMELINE_NOT_READY_TO_DROP_BUTTON, -} from '../../lib/timeline/selectors'; -import { ALL_HOSTS_WIDGET_DRAGGABLE_HOSTS } from '../../lib/hosts/selectors'; -import { HOSTS_PAGE } from '../../lib/urls'; -import { waitForAllHostsWidget } from '../../lib/hosts/helpers'; -import { loginAndWaitForPage } from '../../lib/util/helpers'; -import { drag } from '../../lib/drag_n_drop/helpers'; -import { createNewTimeline, toggleTimelineVisibility } from '../../lib/timeline/helpers'; +} from '../../../screens/timeline/main'; +import { createNewTimeline } from '../../../tasks/timeline/main'; describe('timeline flyout button', () => { before(() => { loginAndWaitForPage(HOSTS_PAGE); + waitForAllHostsToBeLoaded(); }); afterEach(() => { - cy.get('[data-test-subj="kibanaChrome"]').then($page => { - if ($page.find('[data-test-subj="flyoutOverlay"]').length === 1) { - toggleTimelineVisibility(); - } - }); - + openTimelineIfClosed(); createNewTimeline(); }); it('toggles open the timeline', () => { - toggleTimelineVisibility(); - + openTimeline(); cy.get(TIMELINE_FLYOUT_BODY).should('have.css', 'visibility', 'visible'); }); it('sets the flyout button background to euiColorSuccess with a 10% alpha channel when the user starts dragging a host, but is not hovering over the flyout button', () => { - waitForAllHostsWidget(); - - cy.get(ALL_HOSTS_WIDGET_DRAGGABLE_HOSTS) - .first() - .then(host => drag(host)); + dragFirstHostToTimeline(); cy.get(TIMELINE_NOT_READY_TO_DROP_BUTTON).should( 'have.css', diff --git a/x-pack/legacy/plugins/siem/cypress/screens/siem_main.ts b/x-pack/legacy/plugins/siem/cypress/screens/siem_main.ts new file mode 100644 index 0000000000000..d4eeeb036ee95 --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/screens/siem_main.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export const MAIN_PAGE = '[data-test-subj="kibanaChrome"]'; + +export const TIMELINE_TOGGLE_BUTTON = '[data-test-subj="flyoutOverlay"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/screens/timeline/main.ts b/x-pack/legacy/plugins/siem/cypress/screens/timeline/main.ts index 60c9c2ab44372..4c722ffa5f215 100644 --- a/x-pack/legacy/plugins/siem/cypress/screens/timeline/main.ts +++ b/x-pack/legacy/plugins/siem/cypress/screens/timeline/main.ts @@ -32,3 +32,8 @@ export const TIMELINE_DATA_PROVIDERS_EMPTY = export const TIMELINE_DROPPED_DATA_PROVIDERS = '[data-test-subj="dataProviders"] [data-test-subj="providerContainer"]'; + +export const TIMELINE_FLYOUT_BODY = '[data-test-subj="eui-flyout-body"]'; + +export const TIMELINE_NOT_READY_TO_DROP_BUTTON = + '[data-test-subj="flyout-button-not-ready-to-drop"]'; diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/siem_main.ts b/x-pack/legacy/plugins/siem/cypress/tasks/siem_main.ts new file mode 100644 index 0000000000000..8501bb3d94e26 --- /dev/null +++ b/x-pack/legacy/plugins/siem/cypress/tasks/siem_main.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { MAIN_PAGE, TIMELINE_TOGGLE_BUTTON } from '../screens/siem_main'; +import { DEFAULT_TIMEOUT } from '../tasks/login'; + +export const openTimelineIfClosed = () => { + cy.get(MAIN_PAGE).then($page => { + if ($page.find(TIMELINE_TOGGLE_BUTTON).length === 1) { + openTimeline(); + } + }); +}; + +export const openTimeline = () => { + cy.get(TIMELINE_TOGGLE_BUTTON, { timeout: DEFAULT_TIMEOUT }).click(); +}; diff --git a/x-pack/legacy/plugins/siem/cypress/tasks/timeline/main.ts b/x-pack/legacy/plugins/siem/cypress/tasks/timeline/main.ts index 068b6dd9f8bd4..f347c072a3584 100644 --- a/x-pack/legacy/plugins/siem/cypress/tasks/timeline/main.ts +++ b/x-pack/legacy/plugins/siem/cypress/tasks/timeline/main.ts @@ -7,7 +7,6 @@ import { DEFAULT_TIMEOUT } from '../../integration/lib/util/helpers'; import { - TIMELINE_TOGGLE_BUTTON, SEARCH_OR_FILTER_CONTAINER, TIMELINE_FIELDS_BUTTON, SERVER_SIDE_EVENT_COUNT, @@ -19,10 +18,6 @@ import { export const hostExistsQuery = 'host.name: *'; -export const openTimeline = () => { - cy.get(TIMELINE_TOGGLE_BUTTON, { timeout: DEFAULT_TIMEOUT }).click(); -}; - export const populateTimeline = () => { cy.get(`${SEARCH_OR_FILTER_CONTAINER} input`).type(`${hostExistsQuery} {enter}`); cy.get(SERVER_SIDE_EVENT_COUNT, { timeout: DEFAULT_TIMEOUT }) From 5b7734cd4d97b03b487b257c3c68ad5169b76b2f Mon Sep 17 00:00:00 2001 From: Maryia Lapata Date: Tue, 18 Feb 2020 12:54:30 +0300 Subject: [PATCH 20/21] Apply sub url tracking utils to visualize and discover (#57307) * Apply sub url tracking utils to visualize and discover * Update query karma mock * Remove unnecessary chrome legacy calls * Fix typo * Add setActiveUrl * Add unit test for setActiveUrl * Refactoring Co-authored-by: Elastic Machine --- src/legacy/core_plugins/kibana/index.js | 2 + .../kibana/public/discover/plugin.ts | 54 +++++++++++++- .../public/visualize/kibana_services.ts | 3 +- .../kibana/public/visualize/legacy.ts | 9 +-- .../kibana/public/visualize/legacy_imports.ts | 7 -- .../public/visualize/np_ready/application.ts | 3 +- .../visualize/np_ready/editor/editor.js | 7 +- .../np_ready/listing/visualize_listing.js | 17 ++--- .../kibana/public/visualize/plugin.ts | 70 +++++++++++++++---- .../new_platform/new_platform.karma_mock.js | 50 +++++++++++-- .../url/kbn_url_tracker.test.ts | 6 ++ .../state_management/url/kbn_url_tracker.ts | 26 ++++--- 12 files changed, 189 insertions(+), 65 deletions(-) diff --git a/src/legacy/core_plugins/kibana/index.js b/src/legacy/core_plugins/kibana/index.js index ea81193c1dd0a..8e6bae0b588bc 100644 --- a/src/legacy/core_plugins/kibana/index.js +++ b/src/legacy/core_plugins/kibana/index.js @@ -77,6 +77,7 @@ export default function(kibana) { order: -1003, url: `${kbnBaseUrl}#/discover`, euiIconType: 'discoverApp', + disableSubUrlTracking: true, category: DEFAULT_APP_CATEGORIES.analyze, }, { @@ -87,6 +88,7 @@ export default function(kibana) { order: -1002, url: `${kbnBaseUrl}#/visualize`, euiIconType: 'visualizeApp', + disableSubUrlTracking: true, category: DEFAULT_APP_CATEGORIES.analyze, }, { diff --git a/src/legacy/core_plugins/kibana/public/discover/plugin.ts b/src/legacy/core_plugins/kibana/public/discover/plugin.ts index 565382313e369..e8ded9d99f892 100644 --- a/src/legacy/core_plugins/kibana/public/discover/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/discover/plugin.ts @@ -16,11 +16,17 @@ * specific language governing permissions and limitations * under the License. */ + +import { BehaviorSubject } from 'rxjs'; import { i18n } from '@kbn/i18n'; import { AppMountParameters, CoreSetup, CoreStart, Plugin } from 'kibana/public'; import angular, { auto } from 'angular'; import { UiActionsSetup, UiActionsStart } from 'src/plugins/ui_actions/public'; -import { DataPublicPluginStart } from 'src/plugins/data/public'; +import { + DataPublicPluginStart, + DataPublicPluginSetup, + getQueryStateContainer, +} from '../../../../../plugins/data/public'; import { registerFeature } from './np_ready/register_feature'; import './kibana_services'; import { IEmbeddableStart, IEmbeddableSetup } from '../../../../../plugins/embeddable/public'; @@ -30,7 +36,10 @@ import { NavigationPublicPluginStart as NavigationStart } from '../../../../../p import { ChartsPluginStart } from '../../../../../plugins/charts/public'; import { buildServices } from './build_services'; import { SharePluginStart } from '../../../../../plugins/share/public'; -import { KibanaLegacySetup } from '../../../../../plugins/kibana_legacy/public'; +import { + KibanaLegacySetup, + AngularRenderedAppUpdater, +} from '../../../../../plugins/kibana_legacy/public'; import { DocViewsRegistry } from './np_ready/doc_views/doc_views_registry'; import { DocViewInput, DocViewInputFn } from './np_ready/doc_views/doc_views_types'; import { DocViewTable } from './np_ready/components/table/table'; @@ -40,6 +49,7 @@ import { VisualizationsStart, VisualizationsSetup, } from '../../../visualizations/public/np_ready/public'; +import { createKbnUrlTracker } from '../../../../../plugins/kibana_utils/public'; /** * These are the interfaces with your public contracts. You should export these @@ -56,6 +66,7 @@ export interface DiscoverSetupPlugins { kibanaLegacy: KibanaLegacySetup; home: HomePublicPluginSetup; visualizations: VisualizationsSetup; + data: DataPublicPluginSetup; } export interface DiscoverStartPlugins { uiActions: UiActionsStart; @@ -81,6 +92,9 @@ export class DiscoverPlugin implements Plugin { private docViewsRegistry: DocViewsRegistry | null = null; private embeddableInjector: auto.IInjectorService | null = null; private getEmbeddableInjector: (() => Promise) | null = null; + private appStateUpdater = new BehaviorSubject(() => ({})); + private stopUrlTracking: (() => void) | undefined = undefined; + /** * why are those functions public? they are needed for some mocha tests * can be removed once all is Jest @@ -89,6 +103,27 @@ export class DiscoverPlugin implements Plugin { public initializeServices?: () => Promise<{ core: CoreStart; plugins: DiscoverStartPlugins }>; setup(core: CoreSetup, plugins: DiscoverSetupPlugins): DiscoverSetup { + const { querySyncStateContainer, stop: stopQuerySyncStateContainer } = getQueryStateContainer( + plugins.data.query + ); + const { appMounted, appUnMounted, stop: stopUrlTracker } = createKbnUrlTracker({ + baseUrl: core.http.basePath.prepend('/app/kibana'), + defaultSubUrl: '#/discover', + storageKey: 'lastUrl:discover', + navLinkUpdater$: this.appStateUpdater, + toastNotifications: core.notifications.toasts, + stateParams: [ + { + kbnUrlKey: '_g', + stateUpdate$: querySyncStateContainer.state$, + }, + ], + }); + this.stopUrlTracking = () => { + stopQuerySyncStateContainer(); + stopUrlTracker(); + }; + this.getEmbeddableInjector = this.getInjector.bind(this); this.docViewsRegistry = new DocViewsRegistry(this.getEmbeddableInjector); this.docViewsRegistry.addDocView({ @@ -108,6 +143,8 @@ export class DiscoverPlugin implements Plugin { plugins.kibanaLegacy.registerLegacyApp({ id: 'discover', title: 'Discover', + updater$: this.appStateUpdater.asObservable(), + navLinkId: 'kibana:discover', order: -1004, euiIconType: 'discoverApp', mount: async (params: AppMountParameters) => { @@ -117,11 +154,16 @@ export class DiscoverPlugin implements Plugin { if (!this.initializeInnerAngular) { throw Error('Discover plugin method initializeInnerAngular is undefined'); } + appMounted(); await this.initializeServices(); await this.initializeInnerAngular(); const { renderApp } = await import('./np_ready/application'); - return renderApp(innerAngularName, params.element); + const unmount = await renderApp(innerAngularName, params.element); + return () => { + unmount(); + appUnMounted(); + }; }, }); registerFeature(plugins.home); @@ -160,6 +202,12 @@ export class DiscoverPlugin implements Plugin { this.registerEmbeddable(core, plugins); } + stop() { + if (this.stopUrlTracking) { + this.stopUrlTracking(); + } + } + /** * register embeddable with a slimmer embeddable version of inner angular */ diff --git a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts index 6082fb8428ac3..096877d5824c4 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/kibana_services.ts @@ -35,7 +35,6 @@ import { DataPublicPluginStart, IndexPatternsContract } from '../../../../../plu import { VisualizationsStart } from '../../../visualizations/public'; import { SavedVisualizations } from './np_ready/types'; import { UsageCollectionSetup } from '../../../../../plugins/usage_collection/public'; -import { Chrome } from './legacy_imports'; import { KibanaLegacyStart } from '../../../../../plugins/kibana_legacy/public'; export interface VisualizeKibanaServices { @@ -47,7 +46,6 @@ export interface VisualizeKibanaServices { embeddable: IEmbeddableStart; getBasePath: () => string; indexPatterns: IndexPatternsContract; - legacyChrome: Chrome; localStorage: Storage; navigation: NavigationStart; toastNotifications: ToastsStart; @@ -61,6 +59,7 @@ export interface VisualizeKibanaServices { visualizations: VisualizationsStart; usageCollection?: UsageCollectionSetup; I18nContext: I18nStart['Context']; + setActiveUrl: (newUrl: string) => void; } let services: VisualizeKibanaServices | null = null; diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy.ts index bc2d700f6c6a1..fbbc7ab944daf 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/legacy.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/legacy.ts @@ -18,19 +18,14 @@ */ import { PluginInitializerContext } from 'kibana/public'; -import { legacyChrome, npSetup, npStart } from './legacy_imports'; +import { npSetup, npStart } from 'ui/new_platform'; import { start as visualizations } from '../../../visualizations/public/np_ready/public/legacy'; import { plugin } from './index'; const instance = plugin({ env: npSetup.plugins.kibanaLegacy.env, } as PluginInitializerContext); -instance.setup(npSetup.core, { - ...npSetup.plugins, - __LEGACY: { - legacyChrome, - }, -}); +instance.setup(npSetup.core, npSetup.plugins); instance.start(npStart.core, { ...npStart.plugins, visualizations, diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts index ac9fc227406ff..92433799ba420 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts @@ -24,11 +24,6 @@ * directly where they are needed. */ -import chrome from 'ui/chrome'; - -export const legacyChrome = chrome; -export { Chrome } from 'ui/chrome'; - // @ts-ignore export { AppState, AppStateProvider } from 'ui/state_management/app_state'; export { State } from 'ui/state_management/state'; @@ -39,8 +34,6 @@ export { StateManagementConfigProvider } from 'ui/state_management/config_provid export { stateMonitorFactory } from 'ui/state_management/state_monitor_factory'; export { PersistedState } from 'ui/persisted_state'; -export { npSetup, npStart } from 'ui/new_platform'; - export { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; // @ts-ignore export { EventsProvider } from 'ui/events'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts index 3d5fd6605f56b..bd7b478f827a6 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts @@ -45,7 +45,7 @@ import { VisualizeKibanaServices } from '../kibana_services'; let angularModuleInstance: IModule | null = null; -export const renderApp = async ( +export const renderApp = ( element: HTMLElement, appBasePath: string, deps: VisualizeKibanaServices @@ -58,7 +58,6 @@ export const renderApp = async ( { core: deps.core, env: deps.pluginInitializerContext.env }, true ); - // custom routing stuff initVisualizeApp(angularModuleInstance, deps); } const $injector = mountVisualizeApp(appBasePath, element); diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js index 657104344662f..409d4b41fbe69 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js @@ -90,13 +90,13 @@ function VisualizeAppController( }, }, toastNotifications, - legacyChrome, chrome, getBasePath, core: { docLinks }, savedQueryService, uiSettings, I18nContext, + setActiveUrl, } = getServices(); const filterStateManager = new FilterStateManager(globalState, getAppState, filterManager); @@ -580,10 +580,7 @@ function VisualizeAppController( }); // Manually insert a new url so the back button will open the saved visualization. $window.history.pushState({}, '', savedVisualizationParsedUrl.getRootRelativePath()); - // Since we aren't reloading the page, only inserting a new browser history item, we need to manually update - // the last url for this app, so directly clicking on the Visualize tab will also bring the user to the saved - // url, not the unsaved one. - legacyChrome.trackSubUrlForApp('kibana:visualize', savedVisualizationParsedUrl); + setActiveUrl(savedVisualizationParsedUrl.appPath); const lastDashboardAbsoluteUrl = chrome.navLinks.get('kibana:dashboard').url; const dashboardParsedUrl = absoluteToParsedUrl( diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js index cae1e40cd445a..c0cc499b598f0 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js @@ -36,7 +36,6 @@ export function VisualizeListingController($injector, $scope, createNewVis) { const { addBasePath, chrome, - legacyChrome, savedObjectsClient, savedVisualizations, data: { @@ -100,17 +99,13 @@ export function VisualizeListingController($injector, $scope, createNewVis) { selectedItems.map(item => { return savedObjectsClient.delete(item.savedObjectType, item.id); }) - ) - .then(() => { - legacyChrome.untrackNavLinksForDeletedSavedObjects(selectedItems.map(item => item.id)); - }) - .catch(error => { - toastNotifications.addError(error, { - title: i18n.translate('kbn.visualize.visualizeListingDeleteErrorTitle', { - defaultMessage: 'Error deleting visualization', - }), - }); + ).catch(error => { + toastNotifications.addError(error, { + title: i18n.translate('kbn.visualize.visualizeListingDeleteErrorTitle', { + defaultMessage: 'Error deleting visualization', + }), }); + }); }; chrome.setBreadcrumbs([ diff --git a/src/legacy/core_plugins/kibana/public/visualize/plugin.ts b/src/legacy/core_plugins/kibana/public/visualize/plugin.ts index 16715677d1e20..22804685db3cc 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/plugin.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/plugin.ts @@ -17,6 +17,7 @@ * under the License. */ +import { BehaviorSubject } from 'rxjs'; import { i18n } from '@kbn/i18n'; import { @@ -28,12 +29,19 @@ import { SavedObjectsClientContract, } from 'kibana/public'; -import { Storage } from '../../../../../plugins/kibana_utils/public'; -import { DataPublicPluginStart } from '../../../../../plugins/data/public'; +import { Storage, createKbnUrlTracker } from '../../../../../plugins/kibana_utils/public'; +import { + DataPublicPluginStart, + DataPublicPluginSetup, + getQueryStateContainer, +} from '../../../../../plugins/data/public'; import { IEmbeddableStart } from '../../../../../plugins/embeddable/public'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public'; import { SharePluginStart } from '../../../../../plugins/share/public'; -import { KibanaLegacySetup } from '../../../../../plugins/kibana_legacy/public'; +import { + KibanaLegacySetup, + AngularRenderedAppUpdater, +} from '../../../../../plugins/kibana_legacy/public'; import { VisualizationsStart } from '../../../visualizations/public'; import { VisualizeConstants } from './np_ready/visualize_constants'; import { setServices, VisualizeKibanaServices } from './kibana_services'; @@ -42,7 +50,6 @@ import { HomePublicPluginSetup, } from '../../../../../plugins/home/public'; import { UsageCollectionSetup } from '../../../../../plugins/usage_collection/public'; -import { Chrome } from './legacy_imports'; export interface VisualizePluginStartDependencies { data: DataPublicPluginStart; @@ -53,12 +60,10 @@ export interface VisualizePluginStartDependencies { } export interface VisualizePluginSetupDependencies { - __LEGACY: { - legacyChrome: Chrome; - }; home: HomePublicPluginSetup; kibanaLegacy: KibanaLegacySetup; usageCollection?: UsageCollectionSetup; + data: DataPublicPluginSetup; } export class VisualizePlugin implements Plugin { @@ -70,46 +75,72 @@ export class VisualizePlugin implements Plugin { share: SharePluginStart; visualizations: VisualizationsStart; } | null = null; + private appStateUpdater = new BehaviorSubject(() => ({})); + private stopUrlTracking: (() => void) | undefined = undefined; constructor(private initializerContext: PluginInitializerContext) {} public async setup( core: CoreSetup, - { home, kibanaLegacy, __LEGACY, usageCollection }: VisualizePluginSetupDependencies + { home, kibanaLegacy, usageCollection, data }: VisualizePluginSetupDependencies ) { + const { querySyncStateContainer, stop: stopQuerySyncStateContainer } = getQueryStateContainer( + data.query + ); + const { appMounted, appUnMounted, stop: stopUrlTracker, setActiveUrl } = createKbnUrlTracker({ + baseUrl: core.http.basePath.prepend('/app/kibana'), + defaultSubUrl: '#/visualize', + storageKey: 'lastUrl:visualize', + navLinkUpdater$: this.appStateUpdater, + toastNotifications: core.notifications.toasts, + stateParams: [ + { + kbnUrlKey: '_g', + stateUpdate$: querySyncStateContainer.state$, + }, + ], + }); + this.stopUrlTracking = () => { + stopQuerySyncStateContainer(); + stopUrlTracker(); + }; + kibanaLegacy.registerLegacyApp({ id: 'visualize', title: 'Visualize', + updater$: this.appStateUpdater.asObservable(), + navLinkId: 'kibana:visualize', mount: async (params: AppMountParameters) => { const [coreStart] = await core.getStartServices(); + if (this.startDependencies === null) { throw new Error('not started yet'); } + appMounted(); const { savedObjectsClient, embeddable, navigation, visualizations, - data, + data: dataStart, share, } = this.startDependencies; const deps: VisualizeKibanaServices = { - ...__LEGACY, pluginInitializerContext: this.initializerContext, addBasePath: coreStart.http.basePath.prepend, core: coreStart, chrome: coreStart.chrome, - data, + data: dataStart, embeddable, getBasePath: core.http.basePath.get, - indexPatterns: data.indexPatterns, + indexPatterns: dataStart.indexPatterns, localStorage: new Storage(localStorage), navigation, savedObjectsClient, savedVisualizations: visualizations.getSavedVisualizationsLoader(), - savedQueryService: data.query.savedQueries, + savedQueryService: dataStart.query.savedQueries, share, toastNotifications: coreStart.notifications.toasts, uiSettings: coreStart.uiSettings, @@ -118,11 +149,16 @@ export class VisualizePlugin implements Plugin { visualizations, usageCollection, I18nContext: coreStart.i18n.Context, + setActiveUrl, }; setServices(deps); const { renderApp } = await import('./np_ready/application'); - return renderApp(params.element, params.appBasePath, deps); + const unmount = renderApp(params.element, params.appBasePath, deps); + return () => { + unmount(); + appUnMounted(); + }; }, }); @@ -153,4 +189,10 @@ export class VisualizePlugin implements Plugin { visualizations, }; } + + stop() { + if (this.stopUrlTracking) { + this.stopUrlTracking(); + } + } } diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index 4e52f6f6bafec..38b3434ef9c48 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -61,6 +61,10 @@ const mockCore = { }, }; +let refreshInterval = undefined; +let isTimeRangeSelectorEnabled = true; +let isAutoRefreshSelectorEnabled = true; + export const npSetup = { core: mockCore, plugins: { @@ -101,7 +105,14 @@ export const npSetup = { }, query: { filterManager: { + getFetches$: sinon.fake(), + getFilters: sinon.fake(), + getAppFilters: sinon.fake(), getGlobalFilters: sinon.fake(), + removeFilter: sinon.fake(), + addFilters: sinon.fake(), + setFilters: sinon.fake(), + removeAll: sinon.fake(), getUpdates$: mockObservable, }, timefilter: { @@ -110,6 +121,41 @@ export const npSetup = { getRefreshInterval: sinon.fake(), getTimeUpdate$: mockObservable, getRefreshIntervalUpdate$: mockObservable, + getFetch$: mockObservable, + getAutoRefreshFetch$: mockObservable, + getEnabledUpdated$: mockObservable, + getTimeUpdate$: mockObservable, + getRefreshIntervalUpdate$: mockObservable, + isTimeRangeSelectorEnabled: () => { + return isTimeRangeSelectorEnabled; + }, + isAutoRefreshSelectorEnabled: () => { + return isAutoRefreshSelectorEnabled; + }, + disableAutoRefreshSelector: () => { + isAutoRefreshSelectorEnabled = false; + }, + enableAutoRefreshSelector: () => { + isAutoRefreshSelectorEnabled = true; + }, + getRefreshInterval: () => { + return refreshInterval; + }, + setRefreshInterval: interval => { + refreshInterval = interval; + }, + enableTimeRangeSelector: () => { + isTimeRangeSelectorEnabled = true; + }, + disableTimeRangeSelector: () => { + isTimeRangeSelectorEnabled = false; + }, + getTime: sinon.fake(), + setTime: sinon.fake(), + getActiveBounds: sinon.fake(), + getBounds: sinon.fake(), + calculateBounds: sinon.fake(), + createFilter: sinon.fake(), }, history: sinon.fake(), }, @@ -183,10 +229,6 @@ export const npSetup = { }, }; -let refreshInterval = undefined; -let isTimeRangeSelectorEnabled = true; -let isAutoRefreshSelectorEnabled = true; - export const npStart = { core: { chrome: { diff --git a/src/plugins/kibana_utils/public/state_management/url/kbn_url_tracker.test.ts b/src/plugins/kibana_utils/public/state_management/url/kbn_url_tracker.test.ts index 4b17d8517328b..4cf74d991ceb9 100644 --- a/src/plugins/kibana_utils/public/state_management/url/kbn_url_tracker.test.ts +++ b/src/plugins/kibana_utils/public/state_management/url/kbn_url_tracker.test.ts @@ -181,4 +181,10 @@ describe('kbnUrlTracker', () => { `"/app/test#/start?state1=(key1:abc)&state2=(key2:def)"` ); }); + + test('set url to storage when setActiveUrl was called', () => { + createTracker(); + urlTracker.setActiveUrl('/deep/path/4'); + expect(storage.getItem('storageKey')).toEqual('#/deep/path/4'); + }); }); diff --git a/src/plugins/kibana_utils/public/state_management/url/kbn_url_tracker.ts b/src/plugins/kibana_utils/public/state_management/url/kbn_url_tracker.ts index 6f3f64ea7b941..2edd135c184ec 100644 --- a/src/plugins/kibana_utils/public/state_management/url/kbn_url_tracker.ts +++ b/src/plugins/kibana_utils/public/state_management/url/kbn_url_tracker.ts @@ -36,6 +36,7 @@ export interface KbnUrlTracker { * Unregistering the url tracker. This won't reset the current state of the nav link */ stop: () => void; + setActiveUrl: (newUrl: string) => void; } /** @@ -130,20 +131,24 @@ export function createKbnUrlTracker({ } } + function setActiveUrl(newUrl: string) { + const urlWithHashes = baseUrl + '#' + newUrl; + let urlWithStates = ''; + try { + urlWithStates = unhashUrl(urlWithHashes); + } catch (e) { + toastNotifications.addDanger(e.message); + } + + activeUrl = getActiveSubUrl(urlWithStates || urlWithHashes); + storageInstance.setItem(storageKey, activeUrl); + } + function onMountApp() { unsubscribe(); // track current hash when within app unsubscribeURLHistory = historyInstance.listen(location => { - const urlWithHashes = baseUrl + '#' + location.pathname + location.search; - let urlWithStates = ''; - try { - urlWithStates = unhashUrl(urlWithHashes); - } catch (e) { - toastNotifications.addDanger(e.message); - } - - activeUrl = getActiveSubUrl(urlWithStates || urlWithHashes); - storageInstance.setItem(storageKey, activeUrl); + setActiveUrl(location.pathname + location.search); }); } @@ -188,5 +193,6 @@ export function createKbnUrlTracker({ stop() { unsubscribe(); }, + setActiveUrl, }; } From 8bc3fa40425778a8e056eb4d561ff28f3e870c22 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Tue, 18 Feb 2020 13:45:25 +0100 Subject: [PATCH 21/21] Bugfix: Navigation from unsaved dashboard to recently used fails (#57795) Co-authored-by: Elastic Machine --- .../np_ready/dashboard_state_manager.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_state_manager.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_state_manager.ts index fa5354a17b6d9..fe7beafcad18c 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_state_manager.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_state_manager.ts @@ -165,7 +165,7 @@ export class DashboardStateManager { // make sure url ('_a') matches initial state this.kbnUrlStateStorage.set(this.STATE_STORAGE_KEY, initialState, { replace: true }); - // setup state syncing utils. state container will be synched with url into `this.STATE_STORAGE_KEY` query param + // setup state syncing utils. state container will be synced with url into `this.STATE_STORAGE_KEY` query param this.stateSyncRef = syncState({ storageKey: this.STATE_STORAGE_KEY, stateContainer: { @@ -173,10 +173,20 @@ export class DashboardStateManager { set: (state: DashboardAppState | null) => { // sync state required state container to be able to handle null // overriding set() so it could handle null coming from url - this.stateContainer.set({ - ...this.stateDefaults, - ...state, - }); + if (state) { + this.stateContainer.set({ + ...this.stateDefaults, + ...state, + }); + } else { + // Do nothing in case when state from url is empty, + // this fixes: https://github.com/elastic/kibana/issues/57789 + // There are not much cases when state in url could become empty: + // 1. User manually removed `_a` from the url + // 2. Browser is navigating away from the page and most likely there is no `_a` in the url. + // In this case we don't want to do any state updates + // and just allow $scope.$on('destroy') fire later and clean up everything + } }, }, stateStorage: this.kbnUrlStateStorage,